MDEV-6512: InnoDB: Assertion failure in thread 4537024512 in file
buf0buf.cc line 2642. Analysis: innodb_compression_algorithm is a global variable and can change while we are building page compressed page. This could lead page corruption. Fix: Cache innodb_compression_algorithm on local variable before doing any compression or page formating to avoid concurrent change. Improved page verification on debug builds.
This commit is contained in:
parent
4e3796d720
commit
e974b56438
@ -830,6 +830,11 @@ buf_page_print(
|
||||
mach_read_from_4(read_buf + FIL_PAGE_OFFSET),
|
||||
mach_read_from_4(read_buf
|
||||
+ FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID));
|
||||
|
||||
ulint page_type = mach_read_from_4(read_buf + FIL_PAGE_TYPE);
|
||||
|
||||
fprintf(stderr, "InnoDB: page type %ld meaning %s\n", page_type,
|
||||
fil_get_page_type_name(page_type));
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
|
@ -6697,3 +6697,46 @@ fil_space_name(
|
||||
{
|
||||
return (space->name);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Return page type name */
|
||||
char*
|
||||
fil_get_page_type_name(
|
||||
/*===================*/
|
||||
ulint page_type) /*!< in: FIL_PAGE_TYPE */
|
||||
{
|
||||
switch(page_type) {
|
||||
case FIL_PAGE_PAGE_COMPRESSED:
|
||||
return "PAGE_COMPRESSED";
|
||||
case FIL_PAGE_INDEX:
|
||||
return "INDEX";
|
||||
case FIL_PAGE_UNDO_LOG:
|
||||
return "UNDO LOG";
|
||||
case FIL_PAGE_INODE:
|
||||
return "INODE";
|
||||
case FIL_PAGE_IBUF_FREE_LIST:
|
||||
return "IBUF_FREE_LIST";
|
||||
case FIL_PAGE_TYPE_ALLOCATED:
|
||||
return "ALLOCATED";
|
||||
case FIL_PAGE_IBUF_BITMAP:
|
||||
return "IBUF_BITMAP";
|
||||
case FIL_PAGE_TYPE_SYS:
|
||||
return "SYS";
|
||||
case FIL_PAGE_TYPE_TRX_SYS:
|
||||
return "TRX_SYS";
|
||||
case FIL_PAGE_TYPE_FSP_HDR:
|
||||
return "FSP_HDR";
|
||||
case FIL_PAGE_TYPE_XDES:
|
||||
return "XDES";
|
||||
case FIL_PAGE_TYPE_BLOB:
|
||||
return "BLOB";
|
||||
case FIL_PAGE_TYPE_ZBLOB:
|
||||
return "ZBLOB";
|
||||
case FIL_PAGE_TYPE_ZBLOB2:
|
||||
return "ZBLOB2";
|
||||
case FIL_PAGE_TYPE_COMPRESSED:
|
||||
return "ORACLE PAGE COMPRESSED";
|
||||
default:
|
||||
return "PAGE TYPE CORRUPTED";
|
||||
}
|
||||
}
|
||||
|
@ -268,6 +268,9 @@ fil_compress_page(
|
||||
int level = 0;
|
||||
ulint header_len = FIL_PAGE_DATA + FIL_PAGE_COMPRESSED_SIZE;
|
||||
ulint write_size=0;
|
||||
ulint comp_method = innodb_compression_algorithm; /* Cache to avoid
|
||||
change during
|
||||
function execution */
|
||||
|
||||
ut_ad(buf);
|
||||
ut_ad(out_buf);
|
||||
@ -295,7 +298,7 @@ fil_compress_page(
|
||||
|
||||
write_size = UNIV_PAGE_SIZE - header_len;
|
||||
|
||||
switch(innodb_compression_algorithm) {
|
||||
switch(comp_method) {
|
||||
#ifdef HAVE_LZ4
|
||||
case PAGE_LZ4_ALGORITHM:
|
||||
err = LZ4_compress_limitedOutput((const char *)buf,
|
||||
@ -346,6 +349,10 @@ fil_compress_page(
|
||||
(size_t)&write_size);
|
||||
|
||||
if (err != LZMA_OK || write_size > UNIV_PAGE_SIZE-header_len) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Warning: Compression failed for space %lu name %s len %lu err %d write_size %lu\n",
|
||||
space_id, fil_space_name(space), len, err, write_size);
|
||||
|
||||
srv_stats.pages_page_compression_error.inc();
|
||||
*out_len = len;
|
||||
return (buf);
|
||||
@ -367,6 +374,9 @@ fil_compress_page(
|
||||
0);
|
||||
|
||||
if (err != BZ_OK || write_size > UNIV_PAGE_SIZE-header_len) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Warning: Compression failed for space %lu name %s len %lu err %d write_size %lu\n",
|
||||
space_id, fil_space_name(space), len, err, write_size);
|
||||
srv_stats.pages_page_compression_error.inc();
|
||||
*out_len = len;
|
||||
return (buf);
|
||||
@ -408,7 +418,7 @@ fil_compress_page(
|
||||
/* Set up the correct page type */
|
||||
mach_write_to_2(out_buf+FIL_PAGE_TYPE, FIL_PAGE_PAGE_COMPRESSED);
|
||||
/* Set up the flush lsn to be compression algorithm */
|
||||
mach_write_to_8(out_buf+FIL_PAGE_FILE_FLUSH_LSN, innodb_compression_algorithm);
|
||||
mach_write_to_8(out_buf+FIL_PAGE_FILE_FLUSH_LSN, comp_method);
|
||||
/* Set up the actual payload lenght */
|
||||
mach_write_to_2(out_buf+FIL_PAGE_DATA, write_size);
|
||||
|
||||
@ -417,7 +427,25 @@ fil_compress_page(
|
||||
ut_ad(fil_page_is_compressed(out_buf));
|
||||
ut_ad(mach_read_from_4(out_buf+FIL_PAGE_SPACE_OR_CHKSUM) == BUF_NO_CHECKSUM_MAGIC);
|
||||
ut_ad(mach_read_from_2(out_buf+FIL_PAGE_DATA) == write_size);
|
||||
ut_ad(mach_read_from_8(out_buf+FIL_PAGE_FILE_FLUSH_LSN) == (ulint)innodb_compression_algorithm);
|
||||
ut_ad(mach_read_from_8(out_buf+FIL_PAGE_FILE_FLUSH_LSN) == (ulint)comp_method);
|
||||
|
||||
/* Verify that page can be decompressed */
|
||||
{
|
||||
byte *comp_page;
|
||||
byte *uncomp_page;
|
||||
|
||||
comp_page = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE*2));
|
||||
uncomp_page = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE*2));
|
||||
memcpy(comp_page, out_buf, UNIV_PAGE_SIZE);
|
||||
|
||||
fil_decompress_page(uncomp_page, comp_page, len, NULL);
|
||||
if(buf_page_is_corrupted(false, uncomp_page, 0)) {
|
||||
buf_page_print(uncomp_page, 0, BUF_PAGE_PRINT_NO_CRASH);
|
||||
ut_error;
|
||||
}
|
||||
ut_free(comp_page);
|
||||
ut_free(uncomp_page);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
write_size+=header_len;
|
||||
@ -481,7 +509,7 @@ fil_decompress_page(
|
||||
fprintf(stderr,
|
||||
"InnoDB: Note: FIL: Compression buffer not given, allocating...\n");
|
||||
#endif /* UNIV_PAGECOMPRESS_DEBUG */
|
||||
in_buf = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE));
|
||||
in_buf = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE*2));
|
||||
} else {
|
||||
in_buf = page_buf;
|
||||
}
|
||||
|
@ -1073,4 +1073,12 @@ fil_space_name(
|
||||
/*===========*/
|
||||
fil_space_t* space); /*!< in: space */
|
||||
#endif
|
||||
|
||||
/*******************************************************************//**
|
||||
Return page type name */
|
||||
char*
|
||||
fil_get_page_type_name(
|
||||
/*===================*/
|
||||
ulint page_type); /*!< in: FIL_PAGE_TYPE */
|
||||
|
||||
#endif /* fil0fil_h */
|
||||
|
@ -865,6 +865,11 @@ buf_page_print(
|
||||
mach_read_from_4(read_buf + FIL_PAGE_OFFSET),
|
||||
mach_read_from_4(read_buf
|
||||
+ FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID));
|
||||
|
||||
ulint page_type = mach_read_from_4(read_buf + FIL_PAGE_TYPE);
|
||||
|
||||
fprintf(stderr, "InnoDB: page type %ld meaning %s\n", page_type,
|
||||
fil_get_page_type_name(page_type));
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
|
@ -6823,3 +6823,46 @@ fil_space_name(
|
||||
{
|
||||
return (space->name);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Return page type name */
|
||||
char*
|
||||
fil_get_page_type_name(
|
||||
/*===================*/
|
||||
ulint page_type) /*!< in: FIL_PAGE_TYPE */
|
||||
{
|
||||
switch(page_type) {
|
||||
case FIL_PAGE_PAGE_COMPRESSED:
|
||||
return "PAGE_COMPRESSED";
|
||||
case FIL_PAGE_INDEX:
|
||||
return "INDEX";
|
||||
case FIL_PAGE_UNDO_LOG:
|
||||
return "UNDO LOG";
|
||||
case FIL_PAGE_INODE:
|
||||
return "INODE";
|
||||
case FIL_PAGE_IBUF_FREE_LIST:
|
||||
return "IBUF_FREE_LIST";
|
||||
case FIL_PAGE_TYPE_ALLOCATED:
|
||||
return "ALLOCATED";
|
||||
case FIL_PAGE_IBUF_BITMAP:
|
||||
return "IBUF_BITMAP";
|
||||
case FIL_PAGE_TYPE_SYS:
|
||||
return "SYS";
|
||||
case FIL_PAGE_TYPE_TRX_SYS:
|
||||
return "TRX_SYS";
|
||||
case FIL_PAGE_TYPE_FSP_HDR:
|
||||
return "FSP_HDR";
|
||||
case FIL_PAGE_TYPE_XDES:
|
||||
return "XDES";
|
||||
case FIL_PAGE_TYPE_BLOB:
|
||||
return "BLOB";
|
||||
case FIL_PAGE_TYPE_ZBLOB:
|
||||
return "ZBLOB";
|
||||
case FIL_PAGE_TYPE_ZBLOB2:
|
||||
return "ZBLOB2";
|
||||
case FIL_PAGE_TYPE_COMPRESSED:
|
||||
return "ORACLE PAGE COMPRESSED";
|
||||
default:
|
||||
return "PAGE TYPE CORRUPTED";
|
||||
}
|
||||
}
|
||||
|
@ -268,7 +268,9 @@ fil_compress_page(
|
||||
int level = 0;
|
||||
ulint header_len = FIL_PAGE_DATA + FIL_PAGE_COMPRESSED_SIZE;
|
||||
ulint write_size=0;
|
||||
|
||||
ulint comp_method = innodb_compression_algorithm; /* Cache to avoid
|
||||
change during
|
||||
function execution */
|
||||
ut_ad(buf);
|
||||
ut_ad(out_buf);
|
||||
ut_ad(len);
|
||||
@ -295,7 +297,7 @@ fil_compress_page(
|
||||
|
||||
write_size = UNIV_PAGE_SIZE - header_len;
|
||||
|
||||
switch(innodb_compression_algorithm) {
|
||||
switch(comp_method) {
|
||||
#ifdef HAVE_LZ4
|
||||
case PAGE_LZ4_ALGORITHM:
|
||||
err = LZ4_compress_limitedOutput((const char *)buf,
|
||||
@ -346,6 +348,9 @@ fil_compress_page(
|
||||
(size_t)&write_size);
|
||||
|
||||
if (err != LZMA_OK || write_size > UNIV_PAGE_SIZE-header_len) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Warning: Compression failed for space %lu name %s len %lu err %d write_size %lu\n",
|
||||
space_id, fil_space_name(space), len, err, write_size);
|
||||
srv_stats.pages_page_compression_error.inc();
|
||||
*out_len = len;
|
||||
return (buf);
|
||||
@ -367,6 +372,9 @@ fil_compress_page(
|
||||
0);
|
||||
|
||||
if (err != BZ_OK || write_size > UNIV_PAGE_SIZE-header_len) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Warning: Compression failed for space %lu name %s len %lu err %d write_size %lu\n",
|
||||
space_id, fil_space_name(space), len, err, write_size);
|
||||
srv_stats.pages_page_compression_error.inc();
|
||||
*out_len = len;
|
||||
return (buf);
|
||||
@ -407,7 +415,7 @@ fil_compress_page(
|
||||
/* Set up the correct page type */
|
||||
mach_write_to_2(out_buf+FIL_PAGE_TYPE, FIL_PAGE_PAGE_COMPRESSED);
|
||||
/* Set up the flush lsn to be compression algorithm */
|
||||
mach_write_to_8(out_buf+FIL_PAGE_FILE_FLUSH_LSN, innodb_compression_algorithm);
|
||||
mach_write_to_8(out_buf+FIL_PAGE_FILE_FLUSH_LSN, comp_method);
|
||||
/* Set up the actual payload lenght */
|
||||
mach_write_to_2(out_buf+FIL_PAGE_DATA, write_size);
|
||||
|
||||
@ -416,7 +424,25 @@ fil_compress_page(
|
||||
ut_ad(fil_page_is_compressed(out_buf));
|
||||
ut_ad(mach_read_from_4(out_buf+FIL_PAGE_SPACE_OR_CHKSUM) == BUF_NO_CHECKSUM_MAGIC);
|
||||
ut_ad(mach_read_from_2(out_buf+FIL_PAGE_DATA) == write_size);
|
||||
ut_ad(mach_read_from_8(out_buf+FIL_PAGE_FILE_FLUSH_LSN) == (ulint)innodb_compression_algorithm);
|
||||
ut_ad(mach_read_from_8(out_buf+FIL_PAGE_FILE_FLUSH_LSN) == (ulint)comp_method);
|
||||
|
||||
/* Verify that page can be decompressed */
|
||||
{
|
||||
byte *comp_page;
|
||||
byte *uncomp_page;
|
||||
|
||||
comp_page = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE*2));
|
||||
uncomp_page = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE*2));
|
||||
memcpy(comp_page, out_buf, UNIV_PAGE_SIZE);
|
||||
|
||||
fil_decompress_page(uncomp_page, comp_page, len, NULL);
|
||||
if(buf_page_is_corrupted(false, uncomp_page, 0)) {
|
||||
buf_page_print(uncomp_page, 0, BUF_PAGE_PRINT_NO_CRASH);
|
||||
ut_error;
|
||||
}
|
||||
ut_free(comp_page);
|
||||
ut_free(uncomp_page);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
write_size+=header_len;
|
||||
@ -480,7 +506,7 @@ fil_decompress_page(
|
||||
fprintf(stderr,
|
||||
"InnoDB: Note: FIL: Compression buffer not given, allocating...\n");
|
||||
#endif /* UNIV_PAGECOMPRESS_DEBUG */
|
||||
in_buf = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE));
|
||||
in_buf = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE*2));
|
||||
} else {
|
||||
in_buf = page_buf;
|
||||
}
|
||||
|
@ -1117,4 +1117,11 @@ os_file_handle_error_no_exit(
|
||||
const char* file, /*!< in: file name */
|
||||
const ulint line); /*!< in: line */
|
||||
|
||||
/*******************************************************************//**
|
||||
Return page type name */
|
||||
char*
|
||||
fil_get_page_type_name(
|
||||
/*===================*/
|
||||
ulint page_type); /*!< in: FIL_PAGE_TYPE */
|
||||
|
||||
#endif /* fil0fil_h */
|
||||
|
Loading…
x
Reference in New Issue
Block a user