Commit a8075359 authored by Jan Lindström's avatar Jan Lindström

MDEV-8591: Database page corruption on disk or a failed space, Assertion...

MDEV-8591: Database page corruption on disk or a failed space, Assertion failure in file buf0buf.cc line 2856 on querying a table using wrong default encryption key

Improved error messaging to show based on original page before
encryption is page maybe encrypted or just corrupted.
parent 7145ca47
...@@ -1050,6 +1050,8 @@ buf_block_init( ...@@ -1050,6 +1050,8 @@ buf_block_init(
block->page.buf_fix_count = 0; block->page.buf_fix_count = 0;
block->page.io_fix = BUF_IO_NONE; block->page.io_fix = BUF_IO_NONE;
block->page.key_version = 0; block->page.key_version = 0;
block->page.page_encrypted = false;
block->page.page_compressed = false;
block->page.real_size = 0; block->page.real_size = 0;
block->page.write_size = 0; block->page.write_size = 0;
block->modify_clock = 0; block->modify_clock = 0;
...@@ -2837,6 +2839,7 @@ buf_page_get_gen( ...@@ -2837,6 +2839,7 @@ buf_page_get_gen(
retries = BUF_PAGE_READ_MAX_RETRIES; retries = BUF_PAGE_READ_MAX_RETRIES;
); );
} else { } else {
fprintf(stderr, "InnoDB: Error: Unable" fprintf(stderr, "InnoDB: Error: Unable"
" to read tablespace %lu page no" " to read tablespace %lu page no"
" %lu into the buffer pool after" " %lu into the buffer pool after"
...@@ -3588,6 +3591,8 @@ buf_page_init_low( ...@@ -3588,6 +3591,8 @@ buf_page_init_low(
bpage->oldest_modification = 0; bpage->oldest_modification = 0;
bpage->write_size = 0; bpage->write_size = 0;
bpage->key_version = 0; bpage->key_version = 0;
bpage->page_encrypted = false;
bpage->page_compressed = false;
bpage->real_size = 0; bpage->real_size = 0;
bpage->slot = NULL; bpage->slot = NULL;
...@@ -4286,10 +4291,9 @@ buf_page_check_corrupt( ...@@ -4286,10 +4291,9 @@ buf_page_check_corrupt(
ulint zip_size = buf_page_get_zip_size(bpage); ulint zip_size = buf_page_get_zip_size(bpage);
byte* dst_frame = (zip_size) ? bpage->zip.data : byte* dst_frame = (zip_size) ? bpage->zip.data :
((buf_block_t*) bpage)->frame; ((buf_block_t*) bpage)->frame;
unsigned key_version = unsigned key_version = bpage->key_version;
mach_read_from_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); bool page_compressed = bpage->page_encrypted;
bool page_compressed = fil_page_is_compressed(dst_frame); bool page_compressed_encrypted = bpage->page_compressed;
bool page_compressed_encrypted = fil_page_is_compressed_encrypted(dst_frame);
ulint space_id = mach_read_from_4( ulint space_id = mach_read_from_4(
dst_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); dst_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space_id); fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space_id);
...@@ -4299,15 +4303,20 @@ buf_page_check_corrupt( ...@@ -4299,15 +4303,20 @@ buf_page_check_corrupt(
(crypt_data && crypt_data->type != CRYPT_SCHEME_UNENCRYPTED) || (crypt_data && crypt_data->type != CRYPT_SCHEME_UNENCRYPTED) ||
page_compressed || page_compressed_encrypted) { page_compressed || page_compressed_encrypted) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Maybe corruption: Block space_id %lu in file %s maybe corrupted\n" "Maybe corruption: Block space_id %lu in file %s maybe corrupted.",
"Reason could be that key_version in page %u \n" space_id, space ? space->name : "NULL");
"or in crypt_data %p could not be found,\n" ib_logf(IB_LOG_LEVEL_ERROR,
"key management plugin is not found or\n" "Page based on contents %s encrypted.",
"used encryption algorithm or method does not match.\n" (key_version == 0 && page_compressed_encrypted == false) ? "not" : "maybe");
"Page compressed %d, compressed and encrypted %d.\n", ib_logf(IB_LOG_LEVEL_ERROR,
space_id, space ? space->name : "NULL", "Reason could be that key_version %u in page "
key_version, "or in crypt_data %p could not be found.",
crypt_data, key_version, crypt_data);
ib_logf(IB_LOG_LEVEL_ERROR,
"Reason could be also that key management plugin is not found or"
"used encryption algorithm or method does not match.");
ib_logf(IB_LOG_LEVEL_ERROR,
"Based on page page compressed %d, compressed and encrypted %d.",
page_compressed, page_compressed_encrypted); page_compressed, page_compressed_encrypted);
} }
} }
...@@ -4432,43 +4441,40 @@ buf_page_io_complete( ...@@ -4432,43 +4441,40 @@ buf_page_io_complete(
space = fil_space_get_by_id(bpage->space); space = fil_space_get_by_id(bpage->space);
fil_system_exit(); fil_system_exit();
fprintf(stderr, ib_logf(IB_LOG_LEVEL_ERROR,
"InnoDB: Database page corruption on disk" "Database page corruption on disk"
" or a failed\n" " or a failed");
"InnoDB: space %lu file %s read of page %lu.\n" ib_logf(IB_LOG_LEVEL_ERROR,
"InnoDB: You may have to recover" "Space %lu file %s read of page %lu.",
" from a backup.\n",
(ulint)bpage->space, (ulint)bpage->space,
space ? space->name : "NULL", space ? space->name : "NULL",
(ulong) bpage->offset); (ulong) bpage->offset);
ib_logf(IB_LOG_LEVEL_ERROR,
"You may have to recover"
" from a backup.");
buf_page_check_corrupt(bpage);
buf_page_print(frame, buf_page_get_zip_size(bpage), buf_page_print(frame, buf_page_get_zip_size(bpage),
BUF_PAGE_PRINT_NO_CRASH); BUF_PAGE_PRINT_NO_CRASH);
fprintf(stderr,
"InnoDB: Database page corruption on disk" ib_logf(IB_LOG_LEVEL_ERROR,
" or a failed\n" "It is also possible that your operating"
"InnoDB: file read of page %lu.\n" "system has corrupted its own file cache.");
"InnoDB: You may have to recover" ib_logf(IB_LOG_LEVEL_ERROR,
" from a backup.\n", "and rebooting your computer removes the error.");
(ulong) bpage->offset); ib_logf(IB_LOG_LEVEL_ERROR,
fputs("InnoDB: It is also possible that" "If the corrupt page is an index page you can also try to");
" your operating\n" ib_logf(IB_LOG_LEVEL_ERROR,
"InnoDB: system has corrupted its" "fix the corruption by dumping, dropping, and reimporting");
" own file cache\n" ib_logf(IB_LOG_LEVEL_ERROR,
"InnoDB: and rebooting your computer" "the corrupt table. You can use CHECK");
" removes the\n" ib_logf(IB_LOG_LEVEL_ERROR,
"InnoDB: error.\n" "TABLE to scan your table for corruption.");
"InnoDB: If the corrupt page is an index page\n" ib_logf(IB_LOG_LEVEL_ERROR,
"InnoDB: you can also try to" "See also "
" fix the corruption\n" REFMAN "forcing-innodb-recovery.html"
"InnoDB: by dumping, dropping," " about forcing recovery.");
" and reimporting\n"
"InnoDB: the corrupt table."
" You can use CHECK\n"
"InnoDB: TABLE to scan your"
" table for corruption.\n"
"InnoDB: See also "
REFMAN "forcing-innodb-recovery.html\n"
"InnoDB: about forcing recovery.\n", stderr);
if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) { if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
/* If page space id is larger than TRX_SYS_SPACE /* If page space id is larger than TRX_SYS_SPACE
...@@ -4480,10 +4486,8 @@ buf_page_io_complete( ...@@ -4480,10 +4486,8 @@ buf_page_io_complete(
} else { } else {
buf_page_check_corrupt(bpage); buf_page_check_corrupt(bpage);
fputs("InnoDB: Ending processing" ib_logf(IB_LOG_LEVEL_ERROR,
" because of" "Ending processing because of a corrupt database page.");
" a corrupt database page.\n",
stderr);
ut_error; ut_error;
} }
...@@ -5953,6 +5957,11 @@ buf_page_decrypt_after_read( ...@@ -5953,6 +5957,11 @@ buf_page_decrypt_after_read(
return (TRUE); return (TRUE);
} }
/* Store these for corruption check */
bpage->key_version = key_version;
bpage->page_encrypted = page_compressed_encrypted;
bpage->page_compressed = page_compressed;
if (page_compressed) { if (page_compressed) {
/* the page we read is unencrypted */ /* the page we read is unencrypted */
/* Find free slot from temporary memory array */ /* Find free slot from temporary memory array */
......
...@@ -1582,6 +1582,9 @@ struct buf_page_t{ ...@@ -1582,6 +1582,9 @@ struct buf_page_t{
operation needed. */ operation needed. */
unsigned key_version; /*!< key version for this block */ unsigned key_version; /*!< key version for this block */
bool page_encrypted; /*!< page is encrypted */
bool page_compressed;/*!< page is page compressed */
ulint real_size; /*!< Real size of the page ulint real_size; /*!< Real size of the page
Normal pages == UNIV_PAGE_SIZE Normal pages == UNIV_PAGE_SIZE
page compressed pages, payload page compressed pages, payload
......
...@@ -1082,6 +1082,8 @@ buf_block_init( ...@@ -1082,6 +1082,8 @@ buf_block_init(
block->page.buf_fix_count = 0; block->page.buf_fix_count = 0;
block->page.io_fix = BUF_IO_NONE; block->page.io_fix = BUF_IO_NONE;
block->page.key_version = 0; block->page.key_version = 0;
block->page.page_encrypted = false;
block->page.page_compressed = false;
block->page.real_size = 0; block->page.real_size = 0;
block->page.write_size = 0; block->page.write_size = 0;
block->modify_clock = 0; block->modify_clock = 0;
...@@ -2831,6 +2833,7 @@ buf_page_get_gen( ...@@ -2831,6 +2833,7 @@ buf_page_get_gen(
retries = BUF_PAGE_READ_MAX_RETRIES; retries = BUF_PAGE_READ_MAX_RETRIES;
); );
} else { } else {
fprintf(stderr, "InnoDB: Error: Unable" fprintf(stderr, "InnoDB: Error: Unable"
" to read tablespace %lu page no" " to read tablespace %lu page no"
" %lu into the buffer pool after" " %lu into the buffer pool after"
...@@ -3620,6 +3623,8 @@ buf_page_init_low( ...@@ -3620,6 +3623,8 @@ buf_page_init_low(
bpage->oldest_modification = 0; bpage->oldest_modification = 0;
bpage->write_size = 0; bpage->write_size = 0;
bpage->key_version = 0; bpage->key_version = 0;
bpage->page_encrypted = false;
bpage->page_compressed = false;
bpage->real_size = 0; bpage->real_size = 0;
HASH_INVALIDATE(bpage, hash); HASH_INVALIDATE(bpage, hash);
...@@ -4334,10 +4339,9 @@ buf_page_check_corrupt( ...@@ -4334,10 +4339,9 @@ buf_page_check_corrupt(
ulint zip_size = buf_page_get_zip_size(bpage); ulint zip_size = buf_page_get_zip_size(bpage);
byte* dst_frame = (zip_size) ? bpage->zip.data : byte* dst_frame = (zip_size) ? bpage->zip.data :
((buf_block_t*) bpage)->frame; ((buf_block_t*) bpage)->frame;
unsigned key_version = unsigned key_version = bpage->key_version;
mach_read_from_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); bool page_compressed = bpage->page_encrypted;
bool page_compressed = fil_page_is_compressed(dst_frame); bool page_compressed_encrypted = bpage->page_compressed;
bool page_compressed_encrypted = fil_page_is_compressed_encrypted(dst_frame);
ulint space_id = mach_read_from_4( ulint space_id = mach_read_from_4(
dst_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); dst_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space_id); fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space_id);
...@@ -4347,15 +4351,20 @@ buf_page_check_corrupt( ...@@ -4347,15 +4351,20 @@ buf_page_check_corrupt(
(crypt_data && crypt_data->type != CRYPT_SCHEME_UNENCRYPTED) || (crypt_data && crypt_data->type != CRYPT_SCHEME_UNENCRYPTED) ||
page_compressed || page_compressed_encrypted) { page_compressed || page_compressed_encrypted) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Maybe corruption: Block space_id %lu in file %s maybe corrupted\n" "Maybe corruption: Block space_id %lu in file %s maybe corrupted.",
"Reason could be that key_version in page %u \n" space_id, space ? space->name : "NULL");
"or in crypt_data %p could not be found,\n" ib_logf(IB_LOG_LEVEL_ERROR,
"key management plugin is not found or\n" "Page based on contents %s encrypted.",
"used encryption algorithm or method does not match.\n" (key_version == 0 && page_compressed_encrypted == false) ? "not" : "maybe");
"Page compressed %d, compressed and encrypted %d.\n", ib_logf(IB_LOG_LEVEL_ERROR,
space_id, space ? space->name : "NULL", "Reason could be that key_version %u in page "
key_version, "or in crypt_data %p could not be found.",
crypt_data, key_version, crypt_data);
ib_logf(IB_LOG_LEVEL_ERROR,
"Reason could be also that key management plugin is not found or"
"used encryption algorithm or method does not match.");
ib_logf(IB_LOG_LEVEL_ERROR,
"Based on page page compressed %d, compressed and encrypted %d.",
page_compressed, page_compressed_encrypted); page_compressed, page_compressed_encrypted);
} }
} }
...@@ -4481,44 +4490,39 @@ buf_page_io_complete( ...@@ -4481,44 +4490,39 @@ buf_page_io_complete(
fil_system_enter(); fil_system_enter();
space = fil_space_get_by_id(bpage->space); space = fil_space_get_by_id(bpage->space);
fil_system_exit(); fil_system_exit();
fprintf(stderr, ib_logf(IB_LOG_LEVEL_ERROR,
"InnoDB: Database page corruption on disk" "Database page corruption on disk"
" or a failed\n" " or a failed");
"InnoDB: space %lu file %s read of page %lu.\n" ib_logf(IB_LOG_LEVEL_ERROR,
"InnoDB: You may have to recover" "Space %lu file %s read of page %lu.",
" from a backup.\n",
(ulint)bpage->space, (ulint)bpage->space,
space ? space->name : "NULL", space ? space->name : "NULL",
(ulong) bpage->offset); (ulong) bpage->offset);
ib_logf(IB_LOG_LEVEL_ERROR,
"You may have to recover"
" from a backup.");
buf_page_check_corrupt(bpage);
buf_page_print(frame, buf_page_get_zip_size(bpage), buf_page_print(frame, buf_page_get_zip_size(bpage),
BUF_PAGE_PRINT_NO_CRASH); BUF_PAGE_PRINT_NO_CRASH);
fprintf(stderr, ib_logf(IB_LOG_LEVEL_ERROR,
"InnoDB: Database page corruption on disk" "It is also possible that your operating"
" or a failed\n" "system has corrupted its own file cache.");
"InnoDB: file read of page %lu.\n" ib_logf(IB_LOG_LEVEL_ERROR,
"InnoDB: You may have to recover" "and rebooting your computer removes the error.");
" from a backup.\n", ib_logf(IB_LOG_LEVEL_ERROR,
(ulong) bpage->offset); "If the corrupt page is an index page you can also try to");
fputs("InnoDB: It is also possible that" ib_logf(IB_LOG_LEVEL_ERROR,
" your operating\n" "fix the corruption by dumping, dropping, and reimporting");
"InnoDB: system has corrupted its" ib_logf(IB_LOG_LEVEL_ERROR,
" own file cache\n" "the corrupt table. You can use CHECK");
"InnoDB: and rebooting your computer" ib_logf(IB_LOG_LEVEL_ERROR,
" removes the\n" "TABLE to scan your table for corruption.");
"InnoDB: error.\n" ib_logf(IB_LOG_LEVEL_ERROR,
"InnoDB: If the corrupt page is an index page\n" "See also "
"InnoDB: you can also try to" REFMAN "forcing-innodb-recovery.html"
" fix the corruption\n" " about forcing recovery.");
"InnoDB: by dumping, dropping,"
" and reimporting\n"
"InnoDB: the corrupt table."
" You can use CHECK\n"
"InnoDB: TABLE to scan your"
" table for corruption.\n"
"InnoDB: See also "
REFMAN "forcing-innodb-recovery.html\n"
"InnoDB: about forcing recovery.\n", stderr);
if (srv_pass_corrupt_table && bpage->space != 0 if (srv_pass_corrupt_table && bpage->space != 0
&& bpage->space < SRV_LOG_SPACE_FIRST_ID) { && bpage->space < SRV_LOG_SPACE_FIRST_ID) {
...@@ -4536,7 +4540,8 @@ buf_page_io_complete( ...@@ -4536,7 +4540,8 @@ buf_page_io_complete(
dict_table_set_corrupt_by_space(bpage->space, TRUE); dict_table_set_corrupt_by_space(bpage->space, TRUE);
} }
bpage->is_corrupt = TRUE; bpage->is_corrupt = TRUE;
} else }
if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) { if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
/* If page space id is larger than TRX_SYS_SPACE /* If page space id is larger than TRX_SYS_SPACE
(0), we will attempt to mark the corresponding (0), we will attempt to mark the corresponding
...@@ -4547,10 +4552,8 @@ buf_page_io_complete( ...@@ -4547,10 +4552,8 @@ buf_page_io_complete(
} else { } else {
buf_page_check_corrupt(bpage); buf_page_check_corrupt(bpage);
fputs("InnoDB: Ending processing" ib_logf(IB_LOG_LEVEL_ERROR,
" because of" "Ending processing because of a corrupt database page.");
" a corrupt database page.\n",
stderr);
ut_error; ut_error;
} }
...@@ -6081,6 +6084,11 @@ buf_page_decrypt_after_read( ...@@ -6081,6 +6084,11 @@ buf_page_decrypt_after_read(
return (TRUE); return (TRUE);
} }
/* Store these for corruption check */
bpage->key_version = key_version;
bpage->page_encrypted = page_compressed_encrypted;
bpage->page_compressed = page_compressed;
if (page_compressed) { if (page_compressed) {
/* the page we read is unencrypted */ /* the page we read is unencrypted */
/* Find free slot from temporary memory array */ /* Find free slot from temporary memory array */
......
...@@ -1614,6 +1614,8 @@ struct buf_page_t{ ...@@ -1614,6 +1614,8 @@ struct buf_page_t{
operation needed. */ operation needed. */
unsigned key_version; /*!< key version for this block */ unsigned key_version; /*!< key version for this block */
bool page_encrypted; /*!< page is encrypted */
bool page_compressed;/*!< page is page compressed */
ulint real_size; /*!< Real size of the page ulint real_size; /*!< Real size of the page
Normal pages == UNIV_PAGE_SIZE Normal pages == UNIV_PAGE_SIZE
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment