# name : innodb_fast_checksum.patch # introduced : 11 or before # maintainer : Yasufumi # #!!! notice !!! # Any small change to this file in the main branch # should be done or reviewed by the maintainer! --- a/storage/innobase/buf/buf0buf.c +++ b/storage/innobase/buf/buf0buf.c @@ -512,6 +512,27 @@ return(checksum); } +UNIV_INTERN +ulint +buf_calc_page_new_checksum_32( +/*==========================*/ + const byte* page) /*!< in: buffer page */ +{ + ulint checksum; + + checksum = ut_fold_binary(page + FIL_PAGE_OFFSET, + FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET) + + ut_fold_binary(page + FIL_PAGE_DATA, + FIL_PAGE_DATA_ALIGN_32 - FIL_PAGE_DATA) + + ut_fold_binary_32(page + FIL_PAGE_DATA_ALIGN_32, + UNIV_PAGE_SIZE - FIL_PAGE_DATA_ALIGN_32 + - FIL_PAGE_END_LSN_OLD_CHKSUM); + + checksum = checksum & 0xFFFFFFFFUL; + + return(checksum); +} + /********************************************************************//** In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only looked at the first few bytes of the page. This calculates that old @@ -628,9 +649,21 @@ /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id (always equal to 0), to FIL_PAGE_SPACE_OR_CHKSUM */ - if (checksum_field != 0 + if (!srv_fast_checksum + && checksum_field != 0 + && checksum_field != BUF_NO_CHECKSUM_MAGIC + && checksum_field + != buf_calc_page_new_checksum(read_buf)) { + + return(TRUE); + } + + if (srv_fast_checksum + && checksum_field != 0 && checksum_field != BUF_NO_CHECKSUM_MAGIC && checksum_field + != buf_calc_page_new_checksum_32(read_buf) + && checksum_field != buf_calc_page_new_checksum(read_buf)) { return(TRUE); @@ -654,6 +687,7 @@ dict_index_t* index; #endif /* !UNIV_HOTBACKUP */ ulint checksum; + ulint checksum_32; ulint old_checksum; ulint size = zip_size; @@ -740,12 +774,14 @@ checksum = srv_use_checksums ? buf_calc_page_new_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC; + checksum_32 = srv_use_checksums + ? buf_calc_page_new_checksum_32(read_buf) : BUF_NO_CHECKSUM_MAGIC; old_checksum = srv_use_checksums ? buf_calc_page_old_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC; ut_print_timestamp(stderr); fprintf(stderr, - " InnoDB: Page checksum %lu, prior-to-4.0.14-form" + " InnoDB: Page checksum %lu (32bit_calc: %lu), prior-to-4.0.14-form" " checksum %lu\n" "InnoDB: stored checksum %lu, prior-to-4.0.14-form" " stored checksum %lu\n" @@ -754,7 +790,7 @@ "InnoDB: Page number (if stored to page already) %lu,\n" "InnoDB: space id (if created with >= MySQL-4.1.1" " and stored already) %lu\n", - (ulong) checksum, (ulong) old_checksum, + (ulong) checksum, (ulong) checksum_32, (ulong) old_checksum, (ulong) mach_read_from_4(read_buf + FIL_PAGE_SPACE_OR_CHKSUM), (ulong) mach_read_from_4(read_buf + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM), --- a/storage/innobase/buf/buf0flu.c +++ b/storage/innobase/buf/buf0flu.c @@ -1057,7 +1057,9 @@ mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, srv_use_checksums - ? buf_calc_page_new_checksum(page) + ? (!srv_fast_checksum + ? buf_calc_page_new_checksum(page) + : buf_calc_page_new_checksum_32(page)) : BUF_NO_CHECKSUM_MAGIC); /* We overwrite the first 4 bytes of the end lsn field to store --- a/storage/innobase/fil/fil0fil.c +++ b/storage/innobase/fil/fil0fil.c @@ -3103,13 +3103,24 @@ return(TRUE); } - if (checksum_field != 0 + if (!srv_fast_checksum + && checksum_field != 0 && checksum_field != BUF_NO_CHECKSUM_MAGIC && checksum_field != buf_calc_page_new_checksum(page)) { return(TRUE); } + if (srv_fast_checksum + && checksum_field != 0 + && checksum_field != BUF_NO_CHECKSUM_MAGIC + && checksum_field + != buf_calc_page_new_checksum_32(page) + && checksum_field + != buf_calc_page_new_checksum(page)) { + return(TRUE); + } + return(FALSE); } @@ -3125,7 +3136,9 @@ if (!zip_size) { mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, srv_use_checksums - ? buf_calc_page_new_checksum(page) + ? (!srv_fast_checksum + ? buf_calc_page_new_checksum(page) + : buf_calc_page_new_checksum_32(page)) : BUF_NO_CHECKSUM_MAGIC); mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM, srv_use_checksums --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -183,6 +183,7 @@ #endif /* UNIV_LOG_ARCHIVE */ static my_bool innobase_use_doublewrite = TRUE; static my_bool innobase_use_checksums = TRUE; +static my_bool innobase_fast_checksum = FALSE; static my_bool innobase_recovery_stats = TRUE; static my_bool innobase_locks_unsafe_for_binlog = FALSE; static my_bool innobase_overwrite_relay_log_info = FALSE; @@ -2656,6 +2657,7 @@ srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite; srv_use_checksums = (ibool) innobase_use_checksums; + srv_fast_checksum = (ibool) innobase_fast_checksum; srv_blocking_lru_restore = (ibool) innobase_blocking_lru_restore; @@ -11541,6 +11543,15 @@ "Disable with --skip-innodb-checksums.", NULL, NULL, TRUE); +static MYSQL_SYSVAR_BOOL(fast_checksum, innobase_fast_checksum, + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, + "Change the algorithm of checksum for the whole of datapage to 4-bytes word based. " + "The original checksum is checked after the new one. It may be slow for reading page" + " which has orginal checksum. Overwrite the page or recreate the InnoDB database, " + "if you want the entire benefit for performance at once. " + "#### Attention: The checksum is not compatible for normal or disabled version! ####", + NULL, NULL, FALSE); + static MYSQL_SYSVAR_STR(data_home_dir, innobase_data_home_dir, PLUGIN_VAR_READONLY, "The common part for InnoDB table spaces.", @@ -12112,6 +12123,7 @@ MYSQL_SYSVAR(buffer_pool_size), MYSQL_SYSVAR(buffer_pool_instances), MYSQL_SYSVAR(checksums), + MYSQL_SYSVAR(fast_checksum), MYSQL_SYSVAR(commit_concurrency), MYSQL_SYSVAR(concurrency_tickets), MYSQL_SYSVAR(data_file_path), --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -621,6 +621,11 @@ buf_calc_page_new_checksum( /*=======================*/ const byte* page); /*!< in: buffer page */ +UNIV_INTERN +ulint +buf_calc_page_new_checksum_32( +/*==========================*/ + const byte* page); /*!< in: buffer page */ /********************************************************************//** In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only looked at the first few bytes of the page. This calculates that old --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -119,6 +119,7 @@ #define FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID 34 /*!< starting from 4.1.x this contains the space id of the page */ #define FIL_PAGE_DATA 38 /*!< start of the data on the page */ +#define FIL_PAGE_DATA_ALIGN_32 40 /* @} */ /** File page trailer @{ */ #define FIL_PAGE_END_LSN_OLD_CHKSUM 8 /*!< the low 4 bytes of this are used --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -229,6 +229,7 @@ extern ibool srv_use_doublewrite_buf; extern ibool srv_use_checksums; +extern ibool srv_fast_checksum; extern ulong srv_max_buf_pool_modified_pct; extern ulong srv_max_purge_lag; --- a/storage/innobase/include/ut0rnd.h +++ b/storage/innobase/include/ut0rnd.h @@ -124,6 +124,13 @@ const byte* str, /*!< in: string of bytes */ ulint len) /*!< in: length */ __attribute__((pure)); +UNIV_INLINE +ulint +ut_fold_binary_32( +/*==============*/ + const byte* str, /*!< in: string of bytes */ + ulint len) /*!< in: length */ + __attribute__((pure)); /***********************************************************//** Looks for a prime number slightly greater than the given argument. The prime is chosen so that it is not near any power of 2. --- a/storage/innobase/include/ut0rnd.ic +++ b/storage/innobase/include/ut0rnd.ic @@ -226,3 +226,28 @@ return(fold); } + +UNIV_INLINE +ulint +ut_fold_binary_32( +/*==============*/ + const byte* str, /*!< in: string of bytes */ + ulint len) /*!< in: length */ +{ + const ib_uint32_t* str_end = (const ib_uint32_t*) (str + len); + const ib_uint32_t* str_32 = (const ib_uint32_t*) str; + ulint fold = 0; + + ut_ad(str); + /* This function is only for word-aligned data */ + ut_ad(len % 4 == 0); + ut_ad((ulint)str % 4 == 0); + + while (str_32 < str_end) { + fold = ut_fold_ulint_pair(fold, (ulint)(*str_32)); + + str_32++; + } + + return(fold); +} --- a/storage/innobase/srv/srv0srv.c +++ b/storage/innobase/srv/srv0srv.c @@ -419,6 +419,7 @@ UNIV_INTERN ibool srv_use_doublewrite_buf = TRUE; UNIV_INTERN ibool srv_use_checksums = TRUE; +UNIV_INTERN ibool srv_fast_checksum = FALSE; UNIV_INTERN ulong srv_replication_delay = 0; --- /dev/null +++ b/mysql-test/suite/sys_vars/r/innodb_fast_checksum_basic.result @@ -0,0 +1,3 @@ +SELECT @@global.innodb_fast_checksum; +@@global.innodb_fast_checksum +0 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/innodb_fast_checksum_basic.test @@ -0,0 +1 @@ +SELECT @@global.innodb_fast_checksum;