From c362ea3ffdf2b6def0735492dbec3a72342f7859 Mon Sep 17 00:00:00 2001 From: fran Date: Wed, 25 Jun 2014 12:32:22 +0200 Subject: [PATCH 01/12] Added Master_Host to the Replication information Closes #3 --- scripts/mytop.sh | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/scripts/mytop.sh b/scripts/mytop.sh index 480805e90b1..b3dbf5508c6 100644 --- a/scripts/mytop.sh +++ b/scripts/mytop.sh @@ -438,7 +438,7 @@ while (1) if ($key eq 'C') { - if ( $HAS_COLOR ) + if ( $HAS_COLOR ) { $HAS_COLOR = 0; } @@ -818,11 +818,11 @@ sub GetData() if ($config{header}) { my @recs = ""; - if ( $db_release > 4 ) + if ( $db_release > 4 ) { @recs = Hashes("show global status"); - } - else + } + else { @recs = Hashes("show status"); } @@ -979,7 +979,7 @@ sub GetData() # print("q_diff: $STATUS{Questions} - $OLD_STATUS{Questions} / $t_delta = $q_diff\n"); printf(" Sorts: %5.0f qps now: %4.0f Slow qps: %3.1f Threads: %4.0f (%4.0f/%4.0f) %02.0f/%02.0f/%02.0f/%02.0f\n", - ( $STATUS{Sort_rows} - $OLD_STATUS{Sort_rows} ) / $t_delta, + ( $STATUS{Sort_rows} - $OLD_STATUS{Sort_rows} ) / $t_delta, ( $STATUS{Questions} - $OLD_STATUS{Questions} ) / $t_delta, ( # slow now (qps) ($STATUS{Slow_queries} ) ? @@ -990,7 +990,7 @@ sub GetData() $STATUS{Threads_running}, $STATUS{Threads_cached}, - (100 * ($STATUS{Com_select} - $OLD_STATUS{Com_select} + + (100 * ($STATUS{Com_select} - $OLD_STATUS{Com_select} + ($STATUS{Qcache_hits}||0) - ($OLD_STATUS{Qcache_hits}||0) ) ) / ($q_diff ), (100 * ($STATUS{Com_insert} - $OLD_STATUS{Com_insert} + @@ -1076,7 +1076,7 @@ sub GetData() $t_delta, ($STATUS{Rows_tmp_read} - $OLD_STATUS{Rows_tmp_read}) / $t_delta, - ($STATUS{Handler_tmp_write} + ($STATUS{Handler_tmp_write} -$OLD_STATUS{Handler_tmp_write})/$t_delta, ($STATUS{Handler_tmp_update} - $OLD_STATUS{Handler_tmp_update})/$t_delta); @@ -1120,6 +1120,7 @@ sub GetData() } } print " Replication "; + print "Master:$data->{Master_Host} "; print "IO:$data->{Slave_IO_Running} "; print "SQL:$data->{Slave_SQL_Running} "; print RESET() if ($HAS_COLOR); @@ -1226,9 +1227,9 @@ sub GetData() $thread->{State} ||= ""; $thread->{Progress} ||= 0; - ## alter double hyphen comments so they don't break + ## alter double hyphen comments so they don't break ## the query when newlines are removed - http://freshmeat.net/users/jerjones - $thread->{Info} =~ s~\s--(.*)$~ /* $1 */ ~mg; + $thread->{Info} =~ s~\s--(.*)$~ /* $1 */ ~mg; ## Normalize spaces -- mostly disabled for now. This can ## break EXPLAIN if you try to explain a mangled query. It From 32b7d456d5da193c8797e20467f6eac0a6b0c39a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 28 Nov 2018 19:19:16 +0100 Subject: [PATCH 02/12] mysqltest: use a dynamically growing command buffer --- client/mysqltest.cc | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index e41118d742d..088afed41b2 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -6501,8 +6501,6 @@ static inline bool is_escape_char(char c, char in_string) SYNOPSIS read_line - buf buffer for the read line - size size of the buffer i.e max size to read DESCRIPTION This function actually reads several lines and adds them to the @@ -6520,10 +6518,15 @@ static inline bool is_escape_char(char c, char in_string) */ -int read_line(char *buf, int size) +static char *read_command_buf= NULL; +static size_t read_command_buflen= 0; +static const size_t max_multibyte_length= 6; + +int read_line() { char c, last_quote=0, last_char= 0; - char *p= buf, *buf_end= buf + size - 1; + char *p= read_command_buf; + char *buf_end= read_command_buf + read_command_buflen - max_multibyte_length; int skip_char= 0; my_bool have_slash= FALSE; @@ -6531,10 +6534,21 @@ int read_line(char *buf, int size) R_COMMENT, R_LINE_START} state= R_LINE_START; DBUG_ENTER("read_line"); + *p= 0; start_lineno= cur_file->lineno; DBUG_PRINT("info", ("Starting to read at lineno: %d", start_lineno)); - for (; p < buf_end ;) + while (1) { + if (p >= buf_end) + { + my_ptrdiff_t off= p - read_command_buf; + read_command_buf= (char*)my_realloc(read_command_buf, + read_command_buflen*2, MYF(MY_FAE)); + p= read_command_buf + off; + read_command_buflen*= 2; + buf_end= read_command_buf + read_command_buflen - max_multibyte_length; + } + skip_char= 0; c= my_getc(cur_file->file); if (feof(cur_file->file)) @@ -6570,7 +6584,7 @@ int read_line(char *buf, int size) cur_file->lineno++; /* Convert cr/lf to lf */ - if (p != buf && *(p-1) == '\r') + if (p != read_command_buf && *(p-1) == '\r') p--; } @@ -6585,9 +6599,9 @@ int read_line(char *buf, int size) } else if ((c == '{' && (!my_strnncoll_simple(charset_info, (const uchar*) "while", 5, - (uchar*) buf, min(5, p - buf), 0) || + (uchar*) read_command_buf, min(5, p - read_command_buf), 0) || !my_strnncoll_simple(charset_info, (const uchar*) "if", 2, - (uchar*) buf, min(2, p - buf), 0)))) + (uchar*) read_command_buf, min(2, p - read_command_buf), 0)))) { /* Only if and while commands can be terminated by { */ *p++= c; @@ -6721,8 +6735,6 @@ int read_line(char *buf, int size) *p++= c; } } - die("The input buffer is too small for this query.x\n" \ - "check your query or increase MAX_QUERY and recompile"); DBUG_RETURN(0); } @@ -6867,12 +6879,8 @@ bool is_delimiter(const char* p) terminated by new line '\n' regardless how many "delimiter" it contain. */ -#define MAX_QUERY (256*1024*2) /* 256K -- a test in sp-big is >128K */ -static char read_command_buf[MAX_QUERY]; - int read_command(struct st_command** command_ptr) { - char *p= read_command_buf; struct st_command* command; DBUG_ENTER("read_command"); @@ -6888,8 +6896,7 @@ int read_command(struct st_command** command_ptr) die("Out of memory"); command->type= Q_UNKNOWN; - read_command_buf[0]= 0; - if (read_line(read_command_buf, sizeof(read_command_buf))) + if (read_line()) { check_eol_junk(read_command_buf); DBUG_RETURN(1); @@ -6898,6 +6905,7 @@ int read_command(struct st_command** command_ptr) if (opt_result_format_version == 1) convert_to_format_v1(read_command_buf); + char *p= read_command_buf; DBUG_PRINT("info", ("query: '%s'", read_command_buf)); if (*p == '#') { @@ -9025,6 +9033,8 @@ int main(int argc, char **argv) init_win_path_patterns(); #endif + read_command_buf= (char*)my_malloc(read_command_buflen= 65536, MYF(MY_FAE)); + init_dynamic_string(&ds_res, "", 2048, 2048); init_alloc_root(&require_file_root, 1024, 1024); From 9eadef013e77e1622c7c527a1cdfa6dcc2e906dd Mon Sep 17 00:00:00 2001 From: Jiaye Wu Date: Wed, 12 Dec 2018 15:05:14 +0800 Subject: [PATCH 03/12] Fix UNICODE issue of dlerror Current implementation is conflicting. If UNICODE is defined, FormatMessage() will be FormatMessageW(), and variable win_errormsg with type char can not be passed to it, which should be changed to TCHAR instead. Since we don't use UNICODE here, we can use FormatMessageA() directly to avoid conversion error. ``` my_global.h(1092): error C2664: 'DWORD FormatMessageW(D WORD,LPCVOID,DWORD,DWORD,LPWSTR,DWORD,va_list *)' : cannot convert argument 5 from 'char [2048]' to 'LPWSTR' ``` --- include/my_global.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/my_global.h b/include/my_global.h index 816c9dd87c6..fd31de115c8 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -1077,7 +1077,7 @@ typedef ulong myf; /* Type of MyFlags in my_funcs */ static inline char *dlerror(void) { static char win_errormsg[2048]; - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, win_errormsg, 2048, NULL); return win_errormsg; } From c913cd2b669f906f17c87b4c0864ae95b3911e03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 12 Dec 2018 16:31:34 +0200 Subject: [PATCH 04/12] MDEV-17885 TRUNCATE on temporary table causes ER_GET_ERRNO ha_innobase::truncate(): Because CREATE TEMPORARY TABLE allows invalid table options when innodb_file_per_table=1, do allow them also in TRUNCATE for temporary tables. --- mysql-test/suite/innodb/r/truncate.result | 9 +++++++++ mysql-test/suite/innodb/t/truncate.test | 9 +++++++++ storage/innobase/handler/ha_innodb.cc | 3 ++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/innodb/r/truncate.result b/mysql-test/suite/innodb/r/truncate.result index d3ea2716464..5e9fd60d4fe 100644 --- a/mysql-test/suite/innodb/r/truncate.result +++ b/mysql-test/suite/innodb/r/truncate.result @@ -30,3 +30,12 @@ SELECT * FROM t1; a 1 DROP TABLE t1; +# +# MDEV-17885 TRUNCATE on temporary table causes ER_GET_ERRNO +# +CREATE TEMPORARY TABLE t1 (a INT) ENCRYPTED=NO ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); +TRUNCATE t1; +SELECT * FROM t1; +a +DROP TEMPORARY TABLE t1; diff --git a/mysql-test/suite/innodb/t/truncate.test b/mysql-test/suite/innodb/t/truncate.test index 6c573cf42d4..cd1d827e157 100644 --- a/mysql-test/suite/innodb/t/truncate.test +++ b/mysql-test/suite/innodb/t/truncate.test @@ -41,3 +41,12 @@ CREATE TABLE t1 (a INT) ENGINE=InnoDB; --move_file $MYSQLD_DATADIR/test/hidden.frm $MYSQLD_DATADIR/test/t1.frm SELECT * FROM t1; DROP TABLE t1; + +--echo # +--echo # MDEV-17885 TRUNCATE on temporary table causes ER_GET_ERRNO +--echo # +CREATE TEMPORARY TABLE t1 (a INT) ENCRYPTED=NO ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); +TRUNCATE t1; +SELECT * FROM t1; +DROP TEMPORARY TABLE t1; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 717b67290dc..b941ce8b825 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -13531,7 +13531,8 @@ int ha_innobase::truncate() row_mysql_unlock_data_dictionary(trx); } else { err = create(name, table, &info, - dict_table_is_file_per_table(ib_table), trx); + ib_table->is_temporary() + || dict_table_is_file_per_table(ib_table), trx); } trx_free_for_mysql(trx); From 541500295abdba7fa619065069291ac9c1dd6e83 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 11 Dec 2018 11:38:30 +0100 Subject: [PATCH 05/12] debian install/upgrade fixes 1. don't run full mysql_upgrade on every server restart, use --version-check to do it only once 2. fix syslog tag name in the postinst script, don't pretend mysqld_safe generated all these messages. Auto-detect the version to simplify maintenance --- debian/additions/debian-start | 2 +- debian/mariadb-server-10.1.postinst | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/debian/additions/debian-start b/debian/additions/debian-start index 9fd0030d0ec..ff741b86f79 100644 --- a/debian/additions/debian-start +++ b/debian/additions/debian-start @@ -9,7 +9,7 @@ source /usr/share/mysql/debian-start.inc.sh MYSQL="/usr/bin/mysql --defaults-file=/etc/mysql/debian.cnf" MYADMIN="/usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf" -MYUPGRADE="/usr/bin/mysql_upgrade --defaults-extra-file=/etc/mysql/debian.cnf" +MYUPGRADE="/usr/bin/mysql_upgrade --defaults-extra-file=/etc/mysql/debian.cnf --version-check" MYCHECK="/usr/bin/mysqlcheck --defaults-file=/etc/mysql/debian.cnf" MYCHECK_SUBJECT="WARNING: mysqlcheck has found corrupt tables" MYCHECK_PARAMS="--all-databases --fast --silent" diff --git a/debian/mariadb-server-10.1.postinst b/debian/mariadb-server-10.1.postinst index eede069ae12..5382d3d0690 100644 --- a/debian/mariadb-server-10.1.postinst +++ b/debian/mariadb-server-10.1.postinst @@ -2,13 +2,16 @@ . /usr/share/debconf/confmodule +# assume the filename is /path/to/mariadb-server-##.#.postinst +VER=${0: -13:4} + if [ -n "$DEBIAN_SCRIPT_DEBUG" ]; then set -v -x; DEBIAN_SCRIPT_TRACE=1; fi ${DEBIAN_SCRIPT_TRACE:+ echo "#42#DEBUG# RUNNING $0 $*" 1>&2 } export PATH=$PATH:/sbin:/usr/sbin:/bin:/usr/bin # This command can be used as pipe to syslog. With "-s" it also logs to stderr. -ERR_LOGGER="logger -p daemon.err -t mysqld_safe -i" +ERR_LOGGER="logger -p daemon.err -t mariadb-server-$VER.postinst -i" # This will make an error in a logged command immediately apparent by aborting # the install, rather than failing silently and leaving a broken install. set -o pipefail @@ -131,7 +134,7 @@ EOF db_set mysql-server/postrm_remove_database false || true # To avoid downgrades. - touch $mysql_statedir/debian-10.1.flag + touch $mysql_statedir/debian-$VER.flag ## On every reconfiguration the maintenance user is recreated. # From ad3346dddf419aed3e5d16066471fd5022af1795 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 16 Nov 2018 14:00:36 +0100 Subject: [PATCH 06/12] add more dbug helpers for gdb --- sql/item.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sql/item.cc b/sql/item.cc index 81da813a55e..25fb9be22eb 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -10752,6 +10752,9 @@ const char *dbug_print_unit(SELECT_LEX_UNIT *un) return "Couldn't fit into buffer"; } +const char *dbug_print(Item *x) { return dbug_print_item(x); } +const char *dbug_print(SELECT_LEX *x) { return dbug_print_select(x); } +const char *dbug_print(SELECT_LEX_UNIT *x) { return dbug_print_unit(x); } #endif /*DBUG_OFF*/ From ce1669af121f705f85c64daf8e40bf0eac9f7887 Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Thu, 13 Dec 2018 00:26:54 +0530 Subject: [PATCH 07/12] Fix compile error when building without the partition engine --- sql/sql_statistics.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 0c359a29431..2a90269e532 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -3931,9 +3931,8 @@ bool is_stat_table(const char *db, const char *table) bool is_eits_usable(Field *field) { - partition_info *part_info= NULL; #ifdef WITH_PARTITION_STORAGE_ENGINE - part_info= field->table->part_info; + partition_info *part_info= field->table->part_info; #endif /* (1): checks if we have EITS statistics for a particular column @@ -3944,8 +3943,11 @@ bool is_eits_usable(Field *field) */ Column_statistics* col_stats= field->read_stats; if (col_stats && !col_stats->no_stat_values_provided() && //(1) - field->type() != MYSQL_TYPE_GEOMETRY && //(2) - (!part_info || !part_info->field_in_partition_expr(field))) //(3) + field->type() != MYSQL_TYPE_GEOMETRY //(2) + #ifdef WITH_PARTITION_STORAGE_ENGINE + && (!part_info || !part_info->field_in_partition_expr(field)) //(3) + #endif + ) return TRUE; return FALSE; } From 5f5e73f1fe4f34b806b94cf9443348ed6cf14c1e Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Tue, 11 Dec 2018 16:16:11 +0530 Subject: [PATCH 08/12] MDEV-17957 Make Innodb_checksum_algorithm stricter for strict_* values Problem: Innodb_checksum_algorithm checks for all checksum algorithm to validate the page checksum even though the algorithm is specified as strict_crc32, strict_innodb, strict_none. Fix: Remove the checks for all checksum algorithm to validate the page checksum if the algo is specified as strict_* values. --- storage/innobase/buf/buf0buf.cc | 192 ++++++++++++++------------- storage/innobase/include/page0page.h | 15 +-- storage/innobase/include/page0zip.h | 15 --- storage/innobase/page/page0page.cc | 42 ------ storage/innobase/page/page0zip.cc | 103 ++------------ storage/xtradb/buf/buf0buf.cc | 190 +++++++++++++------------- storage/xtradb/include/page0page.h | 18 +-- storage/xtradb/page/page0page.cc | 46 ------- storage/xtradb/page/page0zip.cc | 97 ++------------ 9 files changed, 226 insertions(+), 492 deletions(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 11dceacf592..eb29d46daff 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -581,6 +581,8 @@ buf_page_is_corrupted( ulint checksum_field1; ulint checksum_field2; + ib_uint32_t crc32 = ULINT32_UNDEFINED; + bool crc32_inited = false; if (!zip_size && memcmp(read_buf + FIL_PAGE_LSN + 4, @@ -660,120 +662,124 @@ buf_page_is_corrupted( return(FALSE); } - ulint page_no = mach_read_from_4(read_buf + FIL_PAGE_OFFSET); - ulint space_id = mach_read_from_4(read_buf + FIL_PAGE_SPACE_ID); const srv_checksum_algorithm_t curr_algo = static_cast(srv_checksum_algorithm); switch (curr_algo) { - case SRV_CHECKSUM_ALGORITHM_CRC32: case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32: - - if (buf_page_is_checksum_valid_crc32(read_buf, - checksum_field1, checksum_field2)) { - return(FALSE); + if (buf_page_is_checksum_valid_crc32(read_buf, checksum_field1, + checksum_field2)) { + return FALSE; } - if (buf_page_is_checksum_valid_none(read_buf, - checksum_field1, checksum_field2)) { - if (curr_algo - == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_NONE, - space_id, page_no); - } - - return(FALSE); - } - - if (buf_page_is_checksum_valid_innodb(read_buf, - checksum_field1, checksum_field2)) { - if (curr_algo - == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_INNODB, - space_id, page_no); - } - - return(FALSE); - } - - return(TRUE); - - case SRV_CHECKSUM_ALGORITHM_INNODB: + return TRUE; case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB: - - if (buf_page_is_checksum_valid_innodb(read_buf, - checksum_field1, checksum_field2)) { - return(FALSE); + if (buf_page_is_checksum_valid_innodb(read_buf, checksum_field1, + checksum_field2)) { + return FALSE; } - if (buf_page_is_checksum_valid_none(read_buf, - checksum_field1, checksum_field2)) { - if (curr_algo - == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_NONE, - space_id, page_no); - } - - return(FALSE); - } - - if (buf_page_is_checksum_valid_crc32(read_buf, - checksum_field1, checksum_field2)) { - if (curr_algo - == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_CRC32, - space_id, page_no); - } - - return(FALSE); - } - - return(TRUE); - + return TRUE; case SRV_CHECKSUM_ALGORITHM_STRICT_NONE: - - if (buf_page_is_checksum_valid_none(read_buf, - checksum_field1, checksum_field2)) { - return(FALSE); + if (buf_page_is_checksum_valid_none(read_buf, checksum_field1, + checksum_field2)) { + return FALSE; } - if (buf_page_is_checksum_valid_crc32(read_buf, - checksum_field1, checksum_field2)) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_CRC32, - space_id, page_no); - return(FALSE); + return TRUE; + case SRV_CHECKSUM_ALGORITHM_CRC32: + case SRV_CHECKSUM_ALGORITHM_INNODB: + /* Verify old versions of InnoDB only stored 8 byte lsn to the + start and end of the page. */ + + /* Since innodb_checksum_algorithm is not strict_* allow + any of the algos to match for the old field. */ + + if (checksum_field2 + != mach_read_from_4(read_buf + FIL_PAGE_LSN) + && checksum_field2 != BUF_NO_CHECKSUM_MAGIC) { + + if (srv_checksum_algorithm + == SRV_CHECKSUM_ALGORITHM_CRC32) { + + crc32 = buf_calc_page_crc32(read_buf); + crc32_inited = true; + + if (checksum_field2 != crc32 + && checksum_field2 + != buf_calc_page_old_checksum(read_buf)) { + return TRUE; + } + } else { + ut_ad(srv_checksum_algorithm + == SRV_CHECKSUM_ALGORITHM_INNODB); + + if (checksum_field2 + != buf_calc_page_old_checksum(read_buf)) { + + crc32 = buf_calc_page_crc32(read_buf); + crc32_inited = TRUE; + + if (checksum_field2 != crc32) { + return TRUE; + } + } + } } - if (buf_page_is_checksum_valid_innodb(read_buf, - checksum_field1, checksum_field2)) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_INNODB, - space_id, page_no); - return(FALSE); + /* Old field is fine, check the new field */ + + if (checksum_field1 != 0 + && checksum_field1 != BUF_NO_CHECKSUM_MAGIC) { + + if (srv_checksum_algorithm + == SRV_CHECKSUM_ALGORITHM_CRC32) { + + if (!crc32_inited) { + crc32 = buf_calc_page_crc32(read_buf); + crc32_inited = TRUE; + } + + if (checksum_field1 != crc32 + && checksum_field1 + != buf_calc_page_new_checksum(read_buf)) { + return TRUE; + } + } else { + ut_ad(srv_checksum_algorithm + == SRV_CHECKSUM_ALGORITHM_INNODB); + + if (checksum_field1 + != buf_calc_page_new_checksum(read_buf)) { + + if (!crc32_inited) { + crc32 = buf_calc_page_crc32( + read_buf); + crc32_inited = TRUE; + } + + if (checksum_field1 != crc32) { + return TRUE; + } + } + } } - return(TRUE); + if (crc32_inited + && ((checksum_field1 == crc32 + && checksum_field2 != crc32) + || (checksum_field1 != crc32 + && checksum_field2 == crc32))) { + return TRUE; + } + + break; case SRV_CHECKSUM_ALGORITHM_NONE: - /* should have returned FALSE earlier */ - break; - /* no default so the compiler will emit a warning if new enum - is added and not handled here */ + ut_error; } - ut_error; - return(FALSE); + return FALSE; } /** Dump a page to stderr. diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h index 5cbbe30401f..5a572b1f314 100644 --- a/storage/innobase/include/page0page.h +++ b/storage/innobase/include/page0page.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2016, MariaDB Corporation +Copyright (c) 2013, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1123,19 +1123,6 @@ const rec_t* page_find_rec_max_not_deleted( const page_t* page); -/** Issue a warning when the checksum that is stored in the page is valid, -but different than the global setting innodb_checksum_algorithm. -@param[in] current_algo current checksum algorithm -@param[in] page_checksum page valid checksum -@param[in] space_id tablespace id -@param[in] page_no page number */ -void -page_warn_strict_checksum( - srv_checksum_algorithm_t curr_algo, - srv_checksum_algorithm_t page_checksum, - ulint space_id, - ulint page_no); - #ifdef UNIV_MATERIALIZE #undef UNIV_INLINE #define UNIV_INLINE UNIV_INLINE_ORIGINAL diff --git a/storage/innobase/include/page0zip.h b/storage/innobase/include/page0zip.h index 4e362cec641..0bf77e2fcf3 100644 --- a/storage/innobase/include/page0zip.h +++ b/storage/innobase/include/page0zip.h @@ -546,21 +546,6 @@ from outside the buffer pool. # define UNIV_INLINE UNIV_INLINE_ORIGINAL #endif -#ifdef UNIV_INNOCHECKSUM -/** Issue a warning when the checksum that is stored in the page is valid, -but different than the global setting innodb_checksum_algorithm. -@param[in] current_algo current checksum algorithm -@param[in] page_checksum page valid checksum -@param[in] space_id tablespace id -@param[in] page_no page number */ -void -page_warn_strict_checksum( - srv_checksum_algorithm_t curr_algo, - srv_checksum_algorithm_t page_checksum, - ulint space_id, - ulint page_no); -#endif /* UNIV_INNOCHECKSUM */ - #ifndef UNIV_INNOCHECKSUM #ifndef UNIV_NONINL # include "page0zip.ic" diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index fcd722f3492..dd1136eb23a 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -2807,45 +2807,3 @@ page_find_rec_max_not_deleted( } return(prev_rec); } - -/** Issue a warning when the checksum that is stored in the page is valid, -but different than the global setting innodb_checksum_algorithm. -@param[in] current_algo current checksum algorithm -@param[in] page_checksum page valid checksum -@param[in] space_id tablespace id -@param[in] page_no page number */ -void -page_warn_strict_checksum( - srv_checksum_algorithm_t curr_algo, - srv_checksum_algorithm_t page_checksum, - ulint space_id, - ulint page_no) -{ - srv_checksum_algorithm_t curr_algo_nonstrict; - switch (curr_algo) { - case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32: - curr_algo_nonstrict = SRV_CHECKSUM_ALGORITHM_CRC32; - break; - case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB: - curr_algo_nonstrict = SRV_CHECKSUM_ALGORITHM_INNODB; - break; - case SRV_CHECKSUM_ALGORITHM_STRICT_NONE: - curr_algo_nonstrict = SRV_CHECKSUM_ALGORITHM_NONE; - break; - default: - ut_error; - } - - ib_logf(IB_LOG_LEVEL_WARN, - "innodb_checksum_algorithm is set to \"%s\"" - " but the page [page id: space=" ULINTPF "," - " page number=" ULINTPF "] contains a valid checksum \"%s\"." - " Accepting the page as valid. Change innodb_checksum_algorithm" - " to \"%s\" to silently accept such pages or rewrite all pages" - " so that they contain \"%s\" checksum.", - buf_checksum_algorithm_name(curr_algo), - space_id, page_no, - buf_checksum_algorithm_name(page_checksum), - buf_checksum_algorithm_name(curr_algo_nonstrict), - buf_checksum_algorithm_name(curr_algo_nonstrict)); -} diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index 878a0b8728f..f9a4e38064c 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -2,7 +2,7 @@ Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2014, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -48,8 +48,6 @@ using namespace std; #include "btr0cur.h" #include "page0types.h" #include "log0recv.h" -#else -#define page_warn_strict_checksum(A,B,C,D) #endif /* !UNIV_INNOCHECKSUM */ #include "zlib.h" #ifndef UNIV_HOTBACKUP @@ -4926,13 +4924,6 @@ page_zip_verify_checksum( stored = static_cast(mach_read_from_4( static_cast(data) + FIL_PAGE_SPACE_OR_CHKSUM)); - ulint page_no MY_ATTRIBUTE((unused)) = - mach_read_from_4(static_cast - (data) + FIL_PAGE_OFFSET); - ulint space_id MY_ATTRIBUTE((unused)) = - mach_read_from_4(static_cast - (data) + FIL_PAGE_SPACE_ID); - #if FIL_PAGE_LSN % 8 #error "FIL_PAGE_LSN must be 64 bit aligned" #endif @@ -4974,97 +4965,31 @@ page_zip_verify_checksum( switch (curr_algo) { case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32: - case SRV_CHECKSUM_ALGORITHM_CRC32: - - if (stored == BUF_NO_CHECKSUM_MAGIC) { - if (curr_algo - == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_NONE, - space_id, page_no); - } - - return(TRUE); - } - - innodb = static_cast(page_zip_calc_checksum( - data, size, SRV_CHECKSUM_ALGORITHM_INNODB)); - - if (stored == innodb) { - if (curr_algo - == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_INNODB, - space_id, page_no); - } - - return(TRUE); - } - - break; case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB: - case SRV_CHECKSUM_ALGORITHM_INNODB: - - if (stored == BUF_NO_CHECKSUM_MAGIC) { - if (curr_algo - == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_NONE, - space_id, page_no); - } - - return(TRUE); - } - - crc32 = static_cast(page_zip_calc_checksum( - data, size, SRV_CHECKSUM_ALGORITHM_CRC32)); - - if (stored == crc32) { - if (curr_algo - == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_CRC32, - space_id, page_no); - } - - return(TRUE); - } - - break; case SRV_CHECKSUM_ALGORITHM_STRICT_NONE: + return stored == calc; - crc32 = static_cast(page_zip_calc_checksum( - data, size, SRV_CHECKSUM_ALGORITHM_CRC32)); - - if (stored == crc32) { - page_warn_strict_checksum( - curr_algo, SRV_CHECKSUM_ALGORITHM_CRC32, - space_id, page_no); - + case SRV_CHECKSUM_ALGORITHM_CRC32: + if (stored == BUF_NO_CHECKSUM_MAGIC) { return(TRUE); } + crc32 = calc; innodb = static_cast(page_zip_calc_checksum( data, size, SRV_CHECKSUM_ALGORITHM_INNODB)); - - if (stored == innodb) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_INNODB, - space_id, page_no); - return(TRUE); + break; + case SRV_CHECKSUM_ALGORITHM_INNODB: + if (stored == BUF_NO_CHECKSUM_MAGIC) { + return TRUE; } + crc32 = static_cast(page_zip_calc_checksum( + data, size, SRV_CHECKSUM_ALGORITHM_CRC32)); + innodb = calc; break; case SRV_CHECKSUM_ALGORITHM_NONE: - ut_error; - /* no default so the compiler will emit a warning if new enum - is added and not handled here */ + return TRUE; } - return(FALSE); + return (stored == crc32 || stored == innodb); } diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc index 2d9c47e7ad8..aaaf486dddb 100644 --- a/storage/xtradb/buf/buf0buf.cc +++ b/storage/xtradb/buf/buf0buf.cc @@ -653,6 +653,8 @@ buf_page_is_corrupted( ulint checksum_field1; ulint checksum_field2; + ib_uint32_t crc32 = ULINT32_UNDEFINED; + bool crc32_inited = false; if (!zip_size && memcmp(read_buf + FIL_PAGE_LSN + 4, @@ -732,120 +734,124 @@ buf_page_is_corrupted( return(FALSE); } - ulint page_no = mach_read_from_4(read_buf + FIL_PAGE_OFFSET); - ulint space_id = mach_read_from_4(read_buf + FIL_PAGE_SPACE_ID); const srv_checksum_algorithm_t curr_algo = static_cast(srv_checksum_algorithm); switch (curr_algo) { - case SRV_CHECKSUM_ALGORITHM_CRC32: case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32: - - if (buf_page_is_checksum_valid_crc32(read_buf, - checksum_field1, checksum_field2)) { - return(FALSE); + if (buf_page_is_checksum_valid_crc32(read_buf, checksum_field1, + checksum_field2)) { + return FALSE; } - if (buf_page_is_checksum_valid_none(read_buf, - checksum_field1, checksum_field2)) { - if (curr_algo - == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_NONE, - space_id, page_no); - } + return TRUE; - return(FALSE); - } - - if (buf_page_is_checksum_valid_innodb(read_buf, - checksum_field1, checksum_field2)) { - if (curr_algo - == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_INNODB, - space_id, page_no); - } - - return(FALSE); - } - - return(TRUE); - - case SRV_CHECKSUM_ALGORITHM_INNODB: case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB: - - if (buf_page_is_checksum_valid_innodb(read_buf, - checksum_field1, checksum_field2)) { - return(FALSE); + if (buf_page_is_checksum_valid_innodb(read_buf, checksum_field1, + checksum_field2)) { + return FALSE; } - if (buf_page_is_checksum_valid_none(read_buf, - checksum_field1, checksum_field2)) { - if (curr_algo - == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_NONE, - space_id, page_no); - } - - return(FALSE); - } - - if (buf_page_is_checksum_valid_crc32(read_buf, - checksum_field1, checksum_field2)) { - if (curr_algo - == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_CRC32, - space_id, page_no); - } - - return(FALSE); - } - - return(TRUE); - + return TRUE; case SRV_CHECKSUM_ALGORITHM_STRICT_NONE: - - if (buf_page_is_checksum_valid_none(read_buf, - checksum_field1, checksum_field2)) { - return(FALSE); + if (buf_page_is_checksum_valid_none(read_buf, checksum_field1, + checksum_field2)) { + return FALSE; } - if (buf_page_is_checksum_valid_crc32(read_buf, - checksum_field1, checksum_field2)) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_CRC32, - space_id, page_no); - return(FALSE); + return TRUE; + case SRV_CHECKSUM_ALGORITHM_CRC32: + case SRV_CHECKSUM_ALGORITHM_INNODB: + /* Verify old versions of InnoDB only stored 8 byte lsn to the + start and end of the page. */ + + /* Since innodb_checksum_algorithm is not strict_* allow + any of the algos to match for the old field. */ + + if (checksum_field2 + != mach_read_from_4(read_buf + FIL_PAGE_LSN) + && checksum_field2 != BUF_NO_CHECKSUM_MAGIC) { + + if (srv_checksum_algorithm + == SRV_CHECKSUM_ALGORITHM_CRC32) { + + crc32 = buf_calc_page_crc32(read_buf); + crc32_inited = true; + + if (checksum_field2 != crc32 + && checksum_field2 + != buf_calc_page_old_checksum(read_buf)) { + return TRUE; + } + } else { + ut_ad(srv_checksum_algorithm + == SRV_CHECKSUM_ALGORITHM_INNODB); + + if (checksum_field2 + != buf_calc_page_old_checksum(read_buf)) { + + crc32 = buf_calc_page_crc32(read_buf); + crc32_inited = TRUE; + + if (checksum_field2 != crc32) { + return TRUE; + } + } + } } - if (buf_page_is_checksum_valid_innodb(read_buf, - checksum_field1, checksum_field2)) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_INNODB, - space_id, page_no); - return(FALSE); + /* Old field is fine, check the new field */ + + if (checksum_field1 != 0 + && checksum_field1 != BUF_NO_CHECKSUM_MAGIC) { + + if (srv_checksum_algorithm + == SRV_CHECKSUM_ALGORITHM_CRC32) { + + if (!crc32_inited) { + crc32 = buf_calc_page_crc32(read_buf); + crc32_inited = TRUE; + } + + if (checksum_field1 != crc32 + && checksum_field1 + != buf_calc_page_new_checksum(read_buf)) { + return TRUE; + } + } else { + ut_ad(srv_checksum_algorithm + == SRV_CHECKSUM_ALGORITHM_INNODB); + + if (checksum_field1 + != buf_calc_page_new_checksum(read_buf)) { + + if (!crc32_inited) { + crc32 = buf_calc_page_crc32( + read_buf); + crc32_inited = TRUE; + } + + if (checksum_field1 != crc32) { + return TRUE; + } + } + } } - return(TRUE); + if (crc32_inited + && ((checksum_field1 == crc32 + && checksum_field2 != crc32) + || (checksum_field1 != crc32 + && checksum_field2 == crc32))) { + return TRUE; + } - case SRV_CHECKSUM_ALGORITHM_NONE: - /* should have returned FALSE earlier */ break; - /* no default so the compiler will emit a warning if new enum - is added and not handled here */ + case SRV_CHECKSUM_ALGORITHM_NONE: + ut_error; } - ut_error; - return(FALSE); + return FALSE; } /** Dump a page to stderr. diff --git a/storage/xtradb/include/page0page.h b/storage/xtradb/include/page0page.h index eefa0fa4c5b..26e71ff8081 100644 --- a/storage/xtradb/include/page0page.h +++ b/storage/xtradb/include/page0page.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2013, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1109,23 +1110,6 @@ const rec_t* page_find_rec_max_not_deleted( const page_t* page); -#endif /* #ifndef UNIV_INNOCHECKSUM */ - -/** Issue a warning when the checksum that is stored in the page is valid, -but different than the global setting innodb_checksum_algorithm. -@param[in] current_algo current checksum algorithm -@param[in] page_checksum page valid checksum -@param[in] space_id tablespace id -@param[in] page_no page number */ -void -page_warn_strict_checksum( - srv_checksum_algorithm_t curr_algo, - srv_checksum_algorithm_t page_checksum, - ulint space_id, - ulint page_no); - -#ifndef UNIV_INNOCHECKSUM - #ifdef UNIV_MATERIALIZE #undef UNIV_INLINE #define UNIV_INLINE UNIV_INLINE_ORIGINAL diff --git a/storage/xtradb/page/page0page.cc b/storage/xtradb/page/page0page.cc index 518400a9bf0..76c41941b08 100644 --- a/storage/xtradb/page/page0page.cc +++ b/storage/xtradb/page/page0page.cc @@ -2814,49 +2814,3 @@ page_find_rec_max_not_deleted( } #endif /* #ifndef UNIV_INNOCHECKSUM */ - -/** Issue a warning when the checksum that is stored in the page is valid, -but different than the global setting innodb_checksum_algorithm. -@param[in] current_algo current checksum algorithm -@param[in] page_checksum page valid checksum -@param[in] space_id tablespace id -@param[in] page_no page number */ -void -page_warn_strict_checksum( - srv_checksum_algorithm_t curr_algo, - srv_checksum_algorithm_t page_checksum, - ulint space_id, - ulint page_no) -{ - srv_checksum_algorithm_t curr_algo_nonstrict = srv_checksum_algorithm_t(); - switch (curr_algo) { - case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32: - curr_algo_nonstrict = SRV_CHECKSUM_ALGORITHM_CRC32; - break; - case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB: - curr_algo_nonstrict = SRV_CHECKSUM_ALGORITHM_INNODB; - break; - case SRV_CHECKSUM_ALGORITHM_STRICT_NONE: - curr_algo_nonstrict = SRV_CHECKSUM_ALGORITHM_NONE; - break; - default: - ut_error; - } - -#ifdef UNIV_INNOCHECKSUM - fprintf(stderr, -#else - ib_logf(IB_LOG_LEVEL_WARN, -#endif - "innodb_checksum_algorithm is set to \"%s\"" - " but the page [page id: space=" ULINTPF "," - " page number=" ULINTPF "] contains a valid checksum \"%s\"." - " Accepting the page as valid. Change innodb_checksum_algorithm" - " to \"%s\" to silently accept such pages or rewrite all pages" - " so that they contain \"%s\" checksum.", - buf_checksum_algorithm_name(curr_algo), - space_id, page_no, - buf_checksum_algorithm_name(page_checksum), - buf_checksum_algorithm_name(curr_algo_nonstrict), - buf_checksum_algorithm_name(curr_algo_nonstrict)); -} diff --git a/storage/xtradb/page/page0zip.cc b/storage/xtradb/page/page0zip.cc index 0d2bb7fb986..b9b05db24cc 100644 --- a/storage/xtradb/page/page0zip.cc +++ b/storage/xtradb/page/page0zip.cc @@ -2,7 +2,7 @@ Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2014, SkySQL Ab. All Rights Reserved. +Copyright (c) 2014, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -4934,10 +4934,6 @@ page_zip_verify_checksum( stored = static_cast(mach_read_from_4( static_cast(data) + FIL_PAGE_SPACE_OR_CHKSUM)); - ulint page_no = mach_read_from_4(static_cast (data) + FIL_PAGE_OFFSET); - ulint space_id = mach_read_from_4(static_cast - (data) + FIL_PAGE_SPACE_ID); - #if FIL_PAGE_LSN % 8 #error "FIL_PAGE_LSN must be 64 bit aligned" #endif @@ -4974,97 +4970,30 @@ page_zip_verify_checksum( switch (curr_algo) { case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32: - case SRV_CHECKSUM_ALGORITHM_CRC32: - - if (stored == BUF_NO_CHECKSUM_MAGIC) { - if (curr_algo - == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_NONE, - space_id, page_no); - } - - return(TRUE); - } - - innodb = static_cast(page_zip_calc_checksum( - data, size, SRV_CHECKSUM_ALGORITHM_INNODB)); - - if (stored == innodb) { - if (curr_algo - == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_INNODB, - space_id, page_no); - } - - return(TRUE); - } - - break; case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB: - case SRV_CHECKSUM_ALGORITHM_INNODB: - - if (stored == BUF_NO_CHECKSUM_MAGIC) { - if (curr_algo - == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_NONE, - space_id, page_no); - } - - return(TRUE); - } - - crc32 = static_cast(page_zip_calc_checksum( - data, size, SRV_CHECKSUM_ALGORITHM_CRC32)); - - if (stored == crc32) { - if (curr_algo - == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_CRC32, - space_id, page_no); - } - - return(TRUE); - } - - break; case SRV_CHECKSUM_ALGORITHM_STRICT_NONE: - - crc32 = static_cast(page_zip_calc_checksum( - data, size, SRV_CHECKSUM_ALGORITHM_CRC32)); - - if (stored == crc32) { - page_warn_strict_checksum( - curr_algo, SRV_CHECKSUM_ALGORITHM_CRC32, - space_id, page_no); - + return stored == calc; + case SRV_CHECKSUM_ALGORITHM_CRC32: + if (stored == BUF_NO_CHECKSUM_MAGIC) { return(TRUE); } + crc32 = calc; innodb = static_cast(page_zip_calc_checksum( data, size, SRV_CHECKSUM_ALGORITHM_INNODB)); - - if (stored == innodb) { - page_warn_strict_checksum( - curr_algo, - SRV_CHECKSUM_ALGORITHM_INNODB, - space_id, page_no); + break; + case SRV_CHECKSUM_ALGORITHM_INNODB: + if (stored == BUF_NO_CHECKSUM_MAGIC) { return(TRUE); } + crc32 = static_cast(page_zip_calc_checksum( + data, size, SRV_CHECKSUM_ALGORITHM_CRC32)); + innodb = calc; break; case SRV_CHECKSUM_ALGORITHM_NONE: - ut_error; - /* no default so the compiler will emit a warning if new enum - is added and not handled here */ + return TRUE; } - return(FALSE); + return (stored == crc32 || stored == innodb); } From 5ab91f5914cd632a0615c071e38a1bfff4371303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 13 Dec 2018 12:15:18 +0200 Subject: [PATCH 09/12] Remove space before #ifdef --- sql/sql_statistics.cc | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 2a90269e532..a2e6621055d 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -3601,10 +3601,10 @@ void set_statistics_for_table(THD *thd, TABLE *table) Ideally, EITS should provide per-partition statistics but this is not implemented currently. */ - #ifdef WITH_PARTITION_STORAGE_ENGINE +#ifdef WITH_PARTITION_STORAGE_ENGINE if (table->part_info) table->used_stat_records= table->file->stats.records; - #endif +#endif KEY *key_info, *key_info_end; for (key_info= table->key_info, key_info_end= key_info+table->s->keys; @@ -3931,9 +3931,6 @@ bool is_stat_table(const char *db, const char *table) bool is_eits_usable(Field *field) { - #ifdef WITH_PARTITION_STORAGE_ENGINE - partition_info *part_info= field->table->part_info; - #endif /* (1): checks if we have EITS statistics for a particular column (2): Don't use EITS for GEOMETRY columns @@ -3942,12 +3939,11 @@ bool is_eits_usable(Field *field) such columns would be handled during partition pruning. */ Column_statistics* col_stats= field->read_stats; - if (col_stats && !col_stats->no_stat_values_provided() && //(1) - field->type() != MYSQL_TYPE_GEOMETRY //(2) - #ifdef WITH_PARTITION_STORAGE_ENGINE - && (!part_info || !part_info->field_in_partition_expr(field)) //(3) - #endif - ) - return TRUE; - return FALSE; + return col_stats && !col_stats->no_stat_values_provided() && //(1) + field->type() != MYSQL_TYPE_GEOMETRY && //(2) +#ifdef WITH_PARTITION_STORAGE_ENGINE + (!field->table->part_info || + !field->table->part_info->field_in_partition_expr(field)) && //(3) +#endif + true; } From 8e613458e1ad797b5e2c7870ffe1c3d5100dbbee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 13 Dec 2018 12:36:57 +0200 Subject: [PATCH 10/12] Fix cmake -DWITH_PARTITION_STORAGE_ENGINE:BOOL=OFF This is a backport of a part of commit 18455ec3f1a9c22977f0ed87233852813b53eb49 from 10.1. --- sql/partition_info.cc | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 9d7d0d92686..e6a30c8a7f0 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -2748,23 +2748,6 @@ end: } -bool partition_info::error_if_requires_values() const -{ - switch (part_type) { - case NOT_A_PARTITION: - case HASH_PARTITION: - break; - case RANGE_PARTITION: - my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), "RANGE", "LESS THAN"); - return true; - case LIST_PARTITION: - my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), "LIST", "IN"); - return true; - } - return false; -} - - /** Fix partition data from parser. @@ -3232,3 +3215,19 @@ bool check_partition_dirs(partition_info *part_info) } #endif /* WITH_PARTITION_STORAGE_ENGINE */ + +bool partition_info::error_if_requires_values() const +{ + switch (part_type) { + case NOT_A_PARTITION: + case HASH_PARTITION: + break; + case RANGE_PARTITION: + my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), "RANGE", "LESS THAN"); + return true; + case LIST_PARTITION: + my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), "LIST", "IN"); + return true; + } + return false; +} From 1a780eefc9ff8050b44bca07c981bd6a42bdbaf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 13 Dec 2018 17:57:10 +0200 Subject: [PATCH 11/12] MDEV-17958 Make bug-endian innodb_checksum_algorithm=crc32 optional In MySQL 5.7, it was noticed that files are not portable between big-endian and little-endian processor architectures (such as SPARC and x86), because the original implementation of innodb_checksum_algorithm=crc32 was not byte order agnostic. A byte order agnostic implementation of innodb_checksum_algorithm=crc32 was only added to MySQL 5.7, not backported to 5.6. Consequently, MariaDB Server versions 10.0 and 10.1 only contain the CRC-32C implementation that works incorrectly on big-endian architectures, and MariaDB Server 10.2.2 got the byte-order agnostic CRC-32C implementation from MySQL 5.7. MySQL 5.7 introduced a "legacy crc32" variant that is functionally equivalent to the big-endian version of the original crc32 implementation. Thanks to this variant, old data files can be transferred from big-endian systems to newer versions. Introducing new variants of checksum algorithms (without introducing new names for them, or something on the pages themselves to identify the algorithm) generally is a bad idea, because each checksum algorithm is like a lottery ticket. The more algorithms you try, the more likely it will be for the checksum to match on a corrupted page. So, essentially MySQL 5.7 weakened innodb_checksum_algorithm=crc32, and MariaDB 10.2.2 inherited this weakening. We introduce a build option that together with MDEV-17957 makes innodb_checksum_algorithm=strict_crc32 strict again by only allowing one variant of the checksum to match. WITH_INNODB_BUG_ENDIAN_CRC32: A new cmake option for enabling the bug-compatible "legacy crc32" checksum. This is only enabled on big-endian systems by default, to facilitate an upgrade from MariaDB 10.0 or 10.1. Checked by #ifdef INNODB_BUG_ENDIAN_CRC32. ut_crc32_byte_by_byte: Remove (unused function). legacy_big_endian_checksum: Remove. This variable seems to have unnecessarily complicated the logic. When the weakening is enabled, we must always fall back to the buggy checksum. buf_page_check_crc32(): A helper function to compute one or two CRC-32C variants. --- storage/innobase/buf/buf0buf.cc | 138 ++++++++++-------------- storage/innobase/buf/buf0checksum.cc | 82 ++++++++------ storage/innobase/fil/fil0crypt.cc | 17 ++- storage/innobase/include/buf0buf.h | 4 +- storage/innobase/include/buf0checksum.h | 32 +++--- storage/innobase/include/page0zip.h | 11 +- storage/innobase/include/ut0crc32.h | 8 +- storage/innobase/innodb.cmake | 7 ++ storage/innobase/page/page0zip.cc | 101 ++++++++--------- storage/innobase/ut/ut0crc32.cc | 64 +++-------- 10 files changed, 211 insertions(+), 253 deletions(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index b89c0412a39..747899313c1 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -756,17 +756,14 @@ buf_page_is_zeroes( @param[in] read_buf database page @param[in] checksum_field1 new checksum field @param[in] checksum_field2 old checksum field -@param[in] use_legacy_big_endian use legacy big endian algorithm @return true if the page is in crc32 checksum format. */ bool buf_page_is_checksum_valid_crc32( const byte* read_buf, ulint checksum_field1, - ulint checksum_field2, - bool use_legacy_big_endian) + ulint checksum_field2) { - const uint32_t crc32 = buf_calc_page_crc32(read_buf, - use_legacy_big_endian); + const uint32_t crc32 = buf_calc_page_crc32(read_buf); #ifdef UNIV_INNOCHECKSUM if (log_file @@ -783,17 +780,11 @@ buf_page_is_checksum_valid_crc32( return false; } - if (checksum_field1 == crc32) { - return(true); - } else { - const uint32_t crc32_legacy = buf_calc_page_crc32(read_buf, true); - - if (checksum_field1 == crc32_legacy) { - return(true); - } - } - - return(false); + return checksum_field1 == crc32 +#ifdef INNODB_BUG_ENDIAN_CRC32 + || checksum_field1 == buf_calc_page_crc32(read_buf, true) +#endif + ; } /** Checks if the page is in innodb checksum format. @@ -922,6 +913,29 @@ buf_page_is_checksum_valid_none( && checksum_field1 == BUF_NO_CHECKSUM_MAGIC); } +#ifdef INNODB_BUG_ENDIAN_CRC32 +/** Validate the CRC-32C checksum of a page. +@param[in] page buffer page (srv_page_size bytes) +@param[in] checksum CRC-32C checksum stored on page +@return computed checksum */ +static uint32_t buf_page_check_crc32(const byte* page, uint32_t checksum) +{ + uint32_t crc32 = buf_calc_page_crc32(page); + + if (checksum != crc32) { + crc32 = buf_calc_page_crc32(page, true); + } + + return crc32; +} +#else /* INNODB_BUG_ENDIAN_CRC32 */ +/** Validate the CRC-32C checksum of a page. +@param[in] page buffer page (srv_page_size bytes) +@param[in] checksum CRC-32C checksum stored on page +@return computed checksum */ +# define buf_page_check_crc32(page, checksum) buf_calc_page_crc32(page) +#endif /* INNODB_BUG_ENDIAN_CRC32 */ + /** Check if a page is corrupt. @param[in] check_lsn whether the LSN should be checked @param[in] read_buf database page @@ -1037,26 +1051,20 @@ buf_page_is_corrupted( && *reinterpret_cast( read_buf + FIL_PAGE_LSN) == 0) { - ulint i; - /* make sure that the page is really empty */ - for (ulint i = 0; i < UNIV_PAGE_SIZE; i++) { + for (ulint i = 0; i < page_size.logical(); i++) { if (read_buf[i] != 0) { return(true); } } #ifdef UNIV_INNOCHECKSUM - if (i >= page_size.logical()) { - if (log_file) { - fprintf(log_file, "Page::%llu" - " is empty and uncorrupted\n", - cur_page_num); - } - return(false); + if (log_file) { + fprintf(log_file, "Page::%llu" + " is empty and uncorrupted\n", + cur_page_num); } -#else - return(i < page_size.logical()); #endif /* UNIV_INNOCHECKSUM */ + return(false); } const srv_checksum_algorithm_t curr_algo = @@ -1065,10 +1073,7 @@ buf_page_is_corrupted( switch (curr_algo) { case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32: return !buf_page_is_checksum_valid_crc32( - read_buf, checksum_field1, checksum_field2, false) - && !buf_page_is_checksum_valid_crc32( - read_buf, checksum_field1, checksum_field2, - true); + read_buf, checksum_field1, checksum_field2); case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB: return !buf_page_is_checksum_valid_innodb( read_buf, checksum_field1, checksum_field2); @@ -1111,19 +1116,10 @@ buf_page_is_corrupted( if (srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_CRC32) { - - crc32 = buf_calc_page_crc32( - read_buf, legacy_big_endian_checksum); + crc32 = buf_page_check_crc32(read_buf, + checksum_field2); crc32_inited = true; - if (!legacy_big_endian_checksum - && checksum_field2 != crc32) { - crc32 = buf_calc_page_crc32(read_buf, - true); - legacy_big_endian_checksum = - checksum_field2 == crc32; - } - if (checksum_field2 != crc32 && checksum_field2 != buf_calc_page_old_checksum(read_buf)) { @@ -1135,19 +1131,10 @@ buf_page_is_corrupted( if (checksum_field2 != buf_calc_page_old_checksum(read_buf)) { - crc32 = buf_calc_page_crc32( - read_buf, - legacy_big_endian_checksum); + crc32 = buf_page_check_crc32( + read_buf, checksum_field2); crc32_inited = true; - if (!legacy_big_endian_checksum - && checksum_field2 != crc32) { - crc32 = buf_calc_page_crc32( - read_buf, true); - legacy_big_endian_checksum = - checksum_field2 == crc32; - } - if (checksum_field2 != crc32) { return true; } @@ -1161,18 +1148,9 @@ buf_page_is_corrupted( == SRV_CHECKSUM_ALGORITHM_CRC32) { if (!crc32_inited) { - crc32 = buf_calc_page_crc32( - read_buf, - legacy_big_endian_checksum); + crc32 = buf_page_check_crc32( + read_buf, checksum_field2); crc32_inited = true; - - if (!legacy_big_endian_checksum - && checksum_field2 != crc32) { - crc32 = buf_calc_page_crc32( - read_buf, true); - legacy_big_endian_checksum = - checksum_field2 == crc32; - } } if (checksum_field1 != crc32 @@ -1188,18 +1166,9 @@ buf_page_is_corrupted( != buf_calc_page_new_checksum(read_buf)) { if (!crc32_inited) { - crc32 = buf_calc_page_crc32( - read_buf, - legacy_big_endian_checksum); + crc32 = buf_page_check_crc32( + read_buf, checksum_field2); crc32_inited = true; - - if (!legacy_big_endian_checksum - && checksum_field2 != crc32) { - crc32 = buf_calc_page_crc32( - read_buf, true); - legacy_big_endian_checksum = - checksum_field2 == crc32; - } } if (checksum_field1 != crc32) { @@ -1255,10 +1224,12 @@ buf_page_print(const byte* read_buf, const page_size_t& page_size) << page_zip_calc_checksum( read_buf, page_size.physical(), SRV_CHECKSUM_ALGORITHM_CRC32) +#ifdef INNODB_BUG_ENDIAN_CRC32 << "/" << page_zip_calc_checksum( read_buf, page_size.physical(), SRV_CHECKSUM_ALGORITHM_CRC32, true) +#endif << ", " << buf_checksum_algorithm_name( SRV_CHECKSUM_ALGORITHM_INNODB) @@ -1284,9 +1255,10 @@ buf_page_print(const byte* read_buf, const page_size_t& page_size) } else { const uint32_t crc32 = buf_calc_page_crc32(read_buf); - +#ifdef INNODB_BUG_ENDIAN_CRC32 const uint32_t crc32_legacy = buf_calc_page_crc32(read_buf, true); +#endif /* INNODB_BUG_ENDIAN_CRC32 */ ulint page_type = fil_page_get_type(read_buf); ib::info() << "Uncompressed page, stored checksum in field1 " @@ -1295,7 +1267,10 @@ buf_page_print(const byte* read_buf, const page_size_t& page_size) << ", calculated checksums for field1: " << buf_checksum_algorithm_name( SRV_CHECKSUM_ALGORITHM_CRC32) << " " - << crc32 << "/" << crc32_legacy + << crc32 +#ifdef INNODB_BUG_ENDIAN_CRC32 + << "/" << crc32_legacy +#endif << ", " << buf_checksum_algorithm_name( SRV_CHECKSUM_ALGORITHM_INNODB) << " " @@ -1312,7 +1287,10 @@ buf_page_print(const byte* read_buf, const page_size_t& page_size) << ", calculated checksums for field2: " << buf_checksum_algorithm_name( SRV_CHECKSUM_ALGORITHM_CRC32) << " " - << crc32 << "/" << crc32_legacy + << crc32 +#ifdef INNODB_BUG_ENDIAN_CRC32 + << "/" << crc32_legacy +#endif << ", " << buf_checksum_algorithm_name( SRV_CHECKSUM_ALGORITHM_INNODB) << " " @@ -3950,10 +3928,12 @@ buf_zip_decompress( << ", crc32: " << page_zip_calc_checksum( frame, size, SRV_CHECKSUM_ALGORITHM_CRC32) +#ifdef INNODB_BUG_ENDIAN_CRC32 << "/" << page_zip_calc_checksum( frame, size, SRV_CHECKSUM_ALGORITHM_CRC32, true) +#endif << " innodb: " << page_zip_calc_checksum( frame, size, SRV_CHECKSUM_ALGORITHM_INNODB) diff --git a/storage/innobase/buf/buf0checksum.cc b/storage/innobase/buf/buf0checksum.cc index 78b49e49690..543331de150 100644 --- a/storage/innobase/buf/buf0checksum.cc +++ b/storage/innobase/buf/buf0checksum.cc @@ -39,44 +39,56 @@ ha_innodb.cc:12251: error: cannot convert 'srv_checksum_algorithm_t*' to 'long unsigned int*' in initialization */ ulong srv_checksum_algorithm = SRV_CHECKSUM_ALGORITHM_INNODB; -/** set if we have found pages matching legacy big endian checksum */ -bool legacy_big_endian_checksum = false; -/** Calculates the CRC32 checksum of a page. The value is stored to the page +#ifdef INNODB_BUG_ENDIAN_CRC32 +/** Calculate the CRC32 checksum of a page. The value is stored to the page when it is written to a file and also checked for a match when reading from -the file. When reading we allow both normal CRC32 and CRC-legacy-big-endian -variants. Note that we must be careful to calculate the same value on 32-bit -and 64-bit architectures. -@param[in] page buffer page (UNIV_PAGE_SIZE bytes) -@param[in] use_legacy_big_endian if true then use big endian -byteorder when converting byte strings to integers -@return checksum */ -uint32_t -buf_calc_page_crc32( - const byte* page, - bool use_legacy_big_endian /* = false */) +the file. Note that we must be careful to calculate the same value on all +architectures. +@param[in] page buffer page (srv_page_size bytes) +@param[in] bug_endian whether to use big endian byteorder +when converting byte strings to integers, for bug-compatibility with +big-endian architecture running MySQL 5.6, MariaDB 10.0 or MariaDB 10.1 +@return CRC-32C */ +uint32_t buf_calc_page_crc32(const byte* page, bool bug_endian) { - /* Since the field FIL_PAGE_FILE_FLUSH_LSN, and in versions <= 4.1.x - FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, are written outside the buffer pool - to the first pages of data files, we have to skip them in the page - checksum calculation. - We must also skip the field FIL_PAGE_SPACE_OR_CHKSUM where the - checksum is stored, and also the last 8 bytes of page because - there we store the old formula checksum. */ - - ut_crc32_func_t crc32_func = use_legacy_big_endian - ? ut_crc32_legacy_big_endian - : ut_crc32; - - const uint32_t c1 = crc32_func( - page + FIL_PAGE_OFFSET, - FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION - FIL_PAGE_OFFSET); - - const uint32_t c2 = crc32_func( - page + FIL_PAGE_DATA, - UNIV_PAGE_SIZE - FIL_PAGE_DATA - FIL_PAGE_END_LSN_OLD_CHKSUM); - - return(c1 ^ c2); + return bug_endian + ? ut_crc32_legacy_big_endian( + page + FIL_PAGE_OFFSET, + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + - FIL_PAGE_OFFSET) + ^ ut_crc32_legacy_big_endian(page + FIL_PAGE_DATA, + srv_page_size + - (FIL_PAGE_DATA + + FIL_PAGE_END_LSN_OLD_CHKSUM)) + : ut_crc32(page + FIL_PAGE_OFFSET, + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + - FIL_PAGE_OFFSET) + ^ ut_crc32(page + FIL_PAGE_DATA, + srv_page_size + - (FIL_PAGE_DATA + FIL_PAGE_END_LSN_OLD_CHKSUM)); } +#else +/** Calculate the CRC32 checksum of a page. The value is stored to the page +when it is written to a file and also checked for a match when reading from +the file. Note that we must be careful to calculate the same value on all +architectures. +@param[in] page buffer page (srv_page_size bytes) +@return CRC-32C */ +uint32_t buf_calc_page_crc32(const byte* page) +{ + /* Note: innodb_checksum_algorithm=crc32 could and should have + included the entire page in the checksum, and CRC-32 values + should be combined with the CRC-32 function, not with + exclusive OR. We stick to the current algorithm in order to + remain compatible with old data files. */ + return ut_crc32(page + FIL_PAGE_OFFSET, + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + - FIL_PAGE_OFFSET) + ^ ut_crc32(page + FIL_PAGE_DATA, + srv_page_size + - (FIL_PAGE_DATA + FIL_PAGE_END_LSN_OLD_CHKSUM)); +} +#endif /** Calculate a checksum which is stored to the page when it is written to a file. Note that we must be careful to calculate the same value on diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 6218870f704..854037f7df6 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -2636,10 +2636,8 @@ fil_space_verify_crypt_checksum( srv_checksum_algorithm); switch (algorithm) { case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32: - /* We never supported upgrade from the "legacy crc32" - on big endian systems from MariaDB 10.1 to later. */ valid = buf_page_is_checksum_valid_crc32( - page, checksum1, checksum2, false); + page, checksum1, checksum2); break; case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB: valid = buf_page_is_checksum_valid_innodb( @@ -2649,13 +2647,11 @@ fil_space_verify_crypt_checksum( case SRV_CHECKSUM_ALGORITHM_CRC32: case SRV_CHECKSUM_ALGORITHM_INNODB: case SRV_CHECKSUM_ALGORITHM_NONE: - /* We never supported upgrade from the "legacy crc32" - on big endian systems from MariaDB 10.1 to later. - We also never supported + /* never supported innodb_checksum_algorithm=none or strict_none for encrypted pages. */ valid = buf_page_is_checksum_valid_crc32( - page, checksum1, checksum2, false) + page, checksum1, checksum2) || buf_page_is_checksum_valid_innodb( page, checksum1, checksum2); break; @@ -2684,8 +2680,11 @@ fil_space_verify_crypt_checksum( ib::info() << "If unencrypted: stored checksum [" << checksum1 << ":" << checksum2 << "] calculated crc32 [" - << buf_calc_page_crc32(page, false) << ":" - << buf_calc_page_crc32(page, true) << "] innodb [" + << buf_calc_page_crc32(page) +# ifdef INNODB_BUG_ENDIAN_CRC32 + << ":" << buf_calc_page_crc32(page, true) +# endif /* INNODB_BUG_ENDIAN_CRC32 */ + << "] innodb [" << buf_calc_page_old_checksum(page) << ":" << buf_calc_page_new_checksum(page) << "] LSN " << mach_read_from_4(page + FIL_PAGE_LSN); diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index 8e13b3876e4..da344a3216c 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -716,14 +716,12 @@ buf_block_unfix( @param[in] read_buf database page @param[in] checksum_field1 new checksum field @param[in] checksum_field2 old checksum field -@param[in] use_legacy_big_endian use legacy big endian algorithm @return true if the page is in crc32 checksum format. */ bool buf_page_is_checksum_valid_crc32( const byte* read_buf, ulint checksum_field1, - ulint checksum_field2, - bool use_legacy_big_endian) + ulint checksum_field2) MY_ATTRIBUTE((nonnull(1), warn_unused_result)); /** Checks if the page is in innodb checksum format. diff --git a/storage/innobase/include/buf0checksum.h b/storage/innobase/include/buf0checksum.h index 0bac2b911ee..06eb37906d2 100644 --- a/storage/innobase/include/buf0checksum.h +++ b/storage/innobase/include/buf0checksum.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -29,19 +29,26 @@ Created Aug 11, 2011 Vasil Dimov #include "buf0types.h" +#ifdef INNODB_BUG_ENDIAN_CRC32 /** Calculate the CRC32 checksum of a page. The value is stored to the page when it is written to a file and also checked for a match when reading from -the file. When reading we allow both normal CRC32 and CRC-legacy-big-endian -variants. Note that we must be careful to calculate the same value on 32-bit -and 64-bit architectures. -@param[in] page buffer page (UNIV_PAGE_SIZE bytes) -@param[in] use_legacy_big_endian if true then use big endian -byteorder when converting byte strings to integers -@return checksum */ -uint32_t -buf_calc_page_crc32( - const byte* page, - bool use_legacy_big_endian = false); +the file. Note that we must be careful to calculate the same value on all +architectures. +@param[in] page buffer page (srv_page_size bytes) +@param[in] bug_endian whether to use big endian byteorder +when converting byte strings to integers, for bug-compatibility with +big-endian architecture running MySQL 5.6, MariaDB 10.0 or MariaDB 10.1 +@return CRC-32C */ +uint32_t buf_calc_page_crc32(const byte* page, bool bug_endian = false); +#else +/** Calculate the CRC32 checksum of a page. The value is stored to the page +when it is written to a file and also checked for a match when reading from +the file. Note that we must be careful to calculate the same value on all +architectures. +@param[in] page buffer page (srv_page_size bytes) +@return CRC-32C */ +uint32_t buf_calc_page_crc32(const byte* page); +#endif /** Calculate a checksum which is stored to the page when it is written to a file. Note that we must be careful to calculate the same value on @@ -69,6 +76,5 @@ const char* buf_checksum_algorithm_name(srv_checksum_algorithm_t algo); extern ulong srv_checksum_algorithm; -extern bool legacy_big_endian_checksum; #endif /* buf0checksum_h */ diff --git a/storage/innobase/include/page0zip.h b/storage/innobase/include/page0zip.h index d72d5662f78..f458b29c4b4 100644 --- a/storage/innobase/include/page0zip.h +++ b/storage/innobase/include/page0zip.h @@ -492,16 +492,17 @@ page_zip_parse_compress( @param[in] data compressed page @param[in] size size of compressed page @param[in] algo algorithm to use -@param[in] use_legacy_big_endian only used if algo is -SRV_CHECKSUM_ALGORITHM_CRC32 or SRV_CHECKSUM_ALGORITHM_STRICT_CRC32 - if true -then use big endian byteorder when converting byte strings to integers. @return page checksum */ uint32_t page_zip_calc_checksum( const void* data, ulint size, - srv_checksum_algorithm_t algo, - bool use_legacy_big_endian = false); + srv_checksum_algorithm_t algo +#ifdef INNODB_BUG_ENDIAN_CRC32 + /** for crc32, use the big-endian bug-compatible crc32 variant */ + , bool use_legacy_big_endian = false +#endif +); /**********************************************************************//** Verify a compressed page's checksum. diff --git a/storage/innobase/include/ut0crc32.h b/storage/innobase/include/ut0crc32.h index 36b389b5bd2..175a55e51c0 100644 --- a/storage/innobase/include/ut0crc32.h +++ b/storage/innobase/include/ut0crc32.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, MariaDB Corporation. +Copyright (c) 2016, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -47,13 +47,11 @@ typedef uint32_t (*ut_crc32_func_t)(const byte* ptr, ulint len); /** Pointer to CRC32 calculation function. */ extern ut_crc32_func_t ut_crc32; +#ifdef INNODB_BUG_ENDIAN_CRC32 /** Pointer to CRC32 calculation function, which uses big-endian byte order when converting byte strings to integers internally. */ extern ut_crc32_func_t ut_crc32_legacy_big_endian; - -/** Pointer to CRC32-byte-by-byte calculation function (byte order agnostic, -but very slow). */ -extern ut_crc32_func_t ut_crc32_byte_by_byte; +#endif /* INNODB_BUG_ENDIAN_CRC32 */ extern const char* ut_crc32_implementation; diff --git a/storage/innobase/innodb.cmake b/storage/innobase/innodb.cmake index 7272585dcce..b24343afacd 100644 --- a/storage/innobase/innodb.cmake +++ b/storage/innobase/innodb.cmake @@ -25,6 +25,7 @@ INCLUDE(lzma.cmake) INCLUDE(bzip2.cmake) INCLUDE(snappy.cmake) INCLUDE(numa) +INCLUDE(TestBigEndian) MYSQL_CHECK_LZ4() MYSQL_CHECK_LZO() @@ -32,6 +33,7 @@ MYSQL_CHECK_LZMA() MYSQL_CHECK_BZIP2() MYSQL_CHECK_SNAPPY() MYSQL_CHECK_NUMA() +TEST_BIG_ENDIAN(IS_BIG_ENDIAN) IF(CMAKE_CROSSCOMPILING) # Use CHECK_C_SOURCE_COMPILES instead of CHECK_C_SOURCE_RUNS when @@ -123,6 +125,11 @@ ELSEIF(WITH_INNODB_ROOT_GUESS) ADD_DEFINITIONS(-DBTR_CUR_ADAPT) ENDIF() +OPTION(WITH_INNODB_BUG_ENDIAN_CRC32 "Weaken innodb_checksum_algorithm=crc32 by supporting upgrade from big-endian systems running 5.6/10.0/10.1" ${IS_BIG_ENDIAN}) +IF(WITH_INNODB_BUG_ENDIAN_CRC32) + ADD_DEFINITIONS(-DINNODB_BUG_ENDIAN_CRC32) +ENDIF() + OPTION(WITH_INNODB_EXTRA_DEBUG "Enable extra InnoDB debug checks" OFF) IF(WITH_INNODB_EXTRA_DEBUG) IF(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index 82e95a79f4e..50e22059e7d 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -4909,18 +4909,17 @@ corrupt: @param[in] data compressed page @param[in] size size of compressed page @param[in] algo algorithm to use -@param[in] use_legacy_big_endian only used if algo is -SRV_CHECKSUM_ALGORITHM_CRC32 or SRV_CHECKSUM_ALGORITHM_STRICT_CRC32 - if true -then use big endian byteorder when converting byte strings to integers. -SRV_CHECKSUM_ALGORITHM_CRC32 or SRV_CHECKSUM_ALGORITHM_STRICT_CRC32 - if true -then use big endian byteorder when converting byte strings to integers. @return page checksum */ uint32_t page_zip_calc_checksum( const void* data, ulint size, - srv_checksum_algorithm_t algo, - bool use_legacy_big_endian /* = false */) + srv_checksum_algorithm_t algo +#ifdef INNODB_BUG_ENDIAN_CRC32 + /** for crc32, use the big-endian bug-compatible crc32 variant */ + , bool use_legacy_big_endian +#endif +) { uLong adler; const Bytef* s = static_cast(data); @@ -4931,25 +4930,25 @@ page_zip_calc_checksum( switch (algo) { case SRV_CHECKSUM_ALGORITHM_CRC32: case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32: - { - ut_ad(size > FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); - - ut_crc32_func_t crc32_func = use_legacy_big_endian - ? ut_crc32_legacy_big_endian - : ut_crc32; - - const uint32_t crc32 - = crc32_func( - s + FIL_PAGE_OFFSET, - FIL_PAGE_LSN - FIL_PAGE_OFFSET) - ^ crc32_func( + ut_ad(size > FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); +#ifdef INNODB_BUG_ENDIAN_CRC32 + if (use_legacy_big_endian) { + return ut_crc32_legacy_big_endian(s + FIL_PAGE_OFFSET, + FIL_PAGE_LSN + - FIL_PAGE_OFFSET) + ^ ut_crc32_legacy_big_endian( s + FIL_PAGE_TYPE, 2) - ^ crc32_func( + ^ ut_crc32_legacy_big_endian( s + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, - size - FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); - - return(crc32); + size + - FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); } +#endif + return ut_crc32(s + FIL_PAGE_OFFSET, + FIL_PAGE_LSN - FIL_PAGE_OFFSET) + ^ ut_crc32(s + FIL_PAGE_TYPE, 2) + ^ ut_crc32(s + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, + size - FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); case SRV_CHECKSUM_ALGORITHM_INNODB: case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB: ut_ad(size > FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); @@ -4984,13 +4983,8 @@ page_zip_verify_checksum( const void* data, /*!< in: compressed page */ ulint size) /*!< in: size of compressed page */ { - ib_uint32_t stored; - ib_uint32_t calc; - ib_uint32_t crc32 = 0; - ib_uint32_t innodb = 0; - - stored = static_cast(mach_read_from_4( - static_cast(data) + FIL_PAGE_SPACE_OR_CHKSUM)); + const uint32_t stored = mach_read_from_4( + static_cast(data) + FIL_PAGE_SPACE_OR_CHKSUM); #if FIL_PAGE_LSN % 8 #error "FIL_PAGE_LSN must be 64 bit aligned" @@ -5034,8 +5028,7 @@ page_zip_verify_checksum( return(TRUE); } - calc = static_cast(page_zip_calc_checksum( - data, size, curr_algo)); + uint32_t calc = page_zip_calc_checksum(data, size, curr_algo); #ifdef UNIV_INNOCHECKSUM if (log_file) { @@ -5070,13 +5063,11 @@ page_zip_verify_checksum( switch (curr_algo) { case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32: - calc = page_zip_calc_checksum(data, size, curr_algo, true); - if (calc == stored) { - legacy_big_endian_checksum = true; - return TRUE; - } - - return FALSE; +#ifdef INNODB_BUG_ENDIAN_CRC32 + return stored == page_zip_calc_checksum(data, size, curr_algo, + true); +#endif + /* fall through */ case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB: case SRV_CHECKSUM_ALGORITHM_STRICT_NONE: return FALSE; @@ -5085,29 +5076,29 @@ page_zip_verify_checksum( return(TRUE); } - calc = page_zip_calc_checksum(data, size, curr_algo, true); - crc32 = calc; - - if (crc32 == stored) { - legacy_big_endian_checksum = true; - return TRUE; - } - - innodb = static_cast(page_zip_calc_checksum( - data, size, SRV_CHECKSUM_ALGORITHM_INNODB)); - break; + return +#ifdef INNODB_BUG_ENDIAN_CRC32 + stored == page_zip_calc_checksum(data, size, curr_algo, + true) || +#endif + stored == page_zip_calc_checksum( + data, size, SRV_CHECKSUM_ALGORITHM_INNODB); case SRV_CHECKSUM_ALGORITHM_INNODB: if (stored == BUF_NO_CHECKSUM_MAGIC) { return TRUE; } - crc32 = static_cast(page_zip_calc_checksum( - data, size, SRV_CHECKSUM_ALGORITHM_CRC32)); - innodb = calc; - break; + return stored == page_zip_calc_checksum( + data, size, SRV_CHECKSUM_ALGORITHM_CRC32) +#ifdef INNODB_BUG_ENDIAN_CRC32 + || stored == page_zip_calc_checksum( + data, size, + SRV_CHECKSUM_ALGORITHM_CRC32, true) +#endif + ; case SRV_CHECKSUM_ALGORITHM_NONE: return TRUE; } - return (stored == crc32 || stored == innodb); + return FALSE; } diff --git a/storage/innobase/ut/ut0crc32.cc b/storage/innobase/ut/ut0crc32.cc index cbb571e8f47..0c04cc2fc49 100644 --- a/storage/innobase/ut/ut0crc32.cc +++ b/storage/innobase/ut/ut0crc32.cc @@ -2,7 +2,7 @@ Copyright (c) 2009, 2010 Facebook, Inc. All Rights Reserved. Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, MariaDB Corporation. +Copyright (c) 2016, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -92,13 +92,11 @@ mysys/my_perf.c, contributed by Facebook under the following license. /** Pointer to CRC32 calculation function. */ ut_crc32_func_t ut_crc32; +#ifdef INNODB_BUG_ENDIAN_CRC32 /** Pointer to CRC32 calculation function, which uses big-endian byte order when converting byte strings to integers internally. */ ut_crc32_func_t ut_crc32_legacy_big_endian; - -/** Pointer to CRC32-byte-by-byte calculation function (byte order agnostic, -but very slow). */ -ut_crc32_func_t ut_crc32_byte_by_byte; +#endif /* INNODB_BUG_ENDIAN_CRC32 */ /** Text description of CRC32 implementation */ const char* ut_crc32_implementation; @@ -278,6 +276,7 @@ ut_crc32_64_hw( *len -= 8; } +#ifdef INNODB_BUG_ENDIAN_CRC32 /** Calculate CRC32 over 64-bit byte string using a hardware/CPU instruction. The byte string is converted to a 64-bit integer using big endian byte order. @param[in,out] crc crc32 checksum so far when this function is called, @@ -308,6 +307,7 @@ ut_crc32_64_legacy_big_endian_hw( *data += 8; *len -= 8; } +#endif /* INNODB_BUG_ENDIAN_CRC32 */ /** Calculates CRC32 using hardware/CPU instructions. @param[in] buf data over which to calculate CRC32 @@ -396,6 +396,7 @@ ut_crc32_hw( return(~crc); } +# ifdef INNODB_BUG_ENDIAN_CRC32 /** Calculates CRC32 using hardware/CPU instructions. This function uses big endian byte ordering when converting byte sequence to integers. @@ -445,26 +446,7 @@ ut_crc32_legacy_big_endian_hw( return(~crc); } - -/** Calculates CRC32 using hardware/CPU instructions. -This function processes one byte at a time (very slow) and thus it does -not depend on the byte order of the machine. -@param[in] buf data over which to calculate CRC32 -@param[in] len data length -@return CRC-32C (polynomial 0x11EDC6F41) */ -uint32_t -ut_crc32_byte_by_byte_hw( - const byte* buf, - ulint len) -{ - uint32_t crc = 0xFFFFFFFFU; - - while (len > 0) { - ut_crc32_8_hw(&crc, &buf, &len); - } - - return(~crc); -} +# endif /* INNODB_BUG_ENDIAN_CRC32 */ #endif /* defined(__GNUC__) && defined(__x86_64__) || (_WIN64) */ /* CRC32 software implementation. */ @@ -577,6 +559,7 @@ ut_crc32_64_sw( *len -= 8; } +#ifdef INNODB_BUG_ENDIAN_CRC32 /** Calculate CRC32 over 64-bit byte string using a software implementation. The byte string is converted to a 64-bit integer using big endian byte order. @param[in,out] crc crc32 checksum so far when this function is called, @@ -602,6 +585,7 @@ ut_crc32_64_legacy_big_endian_sw( *data += 8; *len -= 8; } +#endif /* INNODB_BUG_ENDIAN_CRC32 */ /** Calculates CRC32 in software, without using CPU instructions. @param[in] buf data over which to calculate CRC32 @@ -653,6 +637,7 @@ ut_crc32_sw( return(~crc); } +#ifdef INNODB_BUG_ENDIAN_CRC32 /** Calculates CRC32 in software, without using CPU instructions. This function uses big endian byte ordering when converting byte sequence to integers. @@ -704,28 +689,7 @@ ut_crc32_legacy_big_endian_sw( return(~crc); } - -/** Calculates CRC32 in software, without using CPU instructions. -This function processes one byte at a time (very slow) and thus it does -not depend on the byte order of the machine. -@param[in] buf data over which to calculate CRC32 -@param[in] len data length -@return CRC-32C (polynomial 0x11EDC6F41) */ -uint32_t -ut_crc32_byte_by_byte_sw( - const byte* buf, - ulint len) -{ - uint32_t crc = 0xFFFFFFFFU; - - ut_a(ut_crc32_slice8_table_initialized); - - while (len > 0) { - ut_crc32_8_sw(&crc, &buf, &len); - } - - return(~crc); -} +#endif /* INNODB_BUG_ENDIAN_CRC32 */ /********************************************************************//** Initializes the data structures used by ut_crc32*(). Does not do any @@ -736,8 +700,9 @@ ut_crc32_init() { ut_crc32_slice8_table_init(); ut_crc32 = ut_crc32_sw; +#ifdef INNODB_BUG_ENDIAN_CRC32 ut_crc32_legacy_big_endian = ut_crc32_legacy_big_endian_sw; - ut_crc32_byte_by_byte = ut_crc32_byte_by_byte_sw; +#endif /* INNODB_BUG_ENDIAN_CRC32 */ ut_crc32_implementation = "Using generic crc32 instructions"; #if (defined(__GNUC__) && defined(__x86_64__)) || defined(_MSC_VER) @@ -770,8 +735,9 @@ ut_crc32_init() if (features_ecx & 1 << 20) { ut_crc32 = ut_crc32_hw; +#ifdef INNODB_BUG_ENDIAN_CRC32 ut_crc32_legacy_big_endian = ut_crc32_legacy_big_endian_hw; - ut_crc32_byte_by_byte = ut_crc32_byte_by_byte_hw; +#endif /* INNODB_BUG_ENDIAN_CRC32 */ ut_crc32_implementation = "Using SSE2 crc32 instructions"; } From e3dda3d95ee4c09c2ed45ce886ecd25d1fc1ae92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 13 Dec 2018 21:25:12 +0200 Subject: [PATCH 12/12] MDEV-17989 InnoDB: Failing assertion: dict_tf2_is_valid(flags, flags2) With innodb_default_row_format=redundant, InnoDB would crash when using table options that are incompatible with ROW_FORMAT=REDUNDANT. create_table_info_t::m_default_row_format: Cache the value of innodb_default_row_format. create_table_info_t::check_table_options(): Validate ROW_TYPE_DEFAULT with m_default_row_format. create_table_info_t::innobase_table_flags(): Use the cached m_default_row_format. create_table_info_t: Never read m_form->s->row_type. Use m_create_info->row_type instead. dict_tf_set(): Never set invalid flags for ROW_FORMAT=REDUNDANT. ha_innobase::truncate(): Set info.row_type based on the ROW_FORMAT of the current table. --- .../default_row_format_create,redundant.rdiff | 11 ++++ .../innodb/r/default_row_format_create.result | 22 ++++++- .../innodb/t/default_row_format_create.test | 20 +++++- storage/innobase/handler/ha_innodb.cc | 61 +++++++++++++++---- storage/innobase/handler/ha_innodb.h | 13 ++-- storage/innobase/include/dict0dict.ic | 17 +++--- 6 files changed, 112 insertions(+), 32 deletions(-) diff --git a/mysql-test/suite/innodb/r/default_row_format_create,redundant.rdiff b/mysql-test/suite/innodb/r/default_row_format_create,redundant.rdiff index 35aa402edd9..29bc560907e 100644 --- a/mysql-test/suite/innodb/r/default_row_format_create,redundant.rdiff +++ b/mysql-test/suite/innodb/r/default_row_format_create,redundant.rdiff @@ -9,3 +9,14 @@ DROP TABLE t1; CREATE TABLE t1(c1 TEXT,c2 BLOB) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; SHOW TABLE STATUS LIKE 't1'; +@@ -31,8 +31,9 @@ + CREATE TABLE t1 (c1 INT) ENGINE=InnoDB page_compressed=1; + SHOW TABLE STATUS LIKE 't1'; + Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +-t1 InnoDB # Dynamic # # # # # # NULL # NULL NULL latin1_swedish_ci NULL `page_compressed`=1 + DROP TABLE IF EXISTS t1; ++Warnings: ++Note 1051 Unknown table 'test.t1' + SET @save_format = @@GLOBAL.innodb_default_row_format; + SET GLOBAL innodb_default_row_format = redundant; + CREATE TABLE t1 (c1 INT) ENGINE=InnoDB; diff --git a/mysql-test/suite/innodb/r/default_row_format_create.result b/mysql-test/suite/innodb/r/default_row_format_create.result index e80c1283b37..d51a63dbd01 100644 --- a/mysql-test/suite/innodb/r/default_row_format_create.result +++ b/mysql-test/suite/innodb/r/default_row_format_create.result @@ -19,8 +19,26 @@ Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length I t1 InnoDB # Redundant # # # # # # NULL # NULL NULL latin1_swedish_ci NULL row_format=REDUNDANT DROP TABLE t1; CREATE TABLE t1(c1 TEXT,c2 BLOB) ENGINE=InnoDB -ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; +ROW_FORMAT=COMPRESSED; SHOW TABLE STATUS LIKE 't1'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 InnoDB # Compressed # # # # # # NULL # NULL NULL latin1_swedish_ci NULL row_format=COMPRESSED key_block_size=1 +t1 InnoDB # Compressed # # # # # # NULL # NULL NULL latin1_swedish_ci NULL row_format=COMPRESSED +TRUNCATE TABLE t1; +SHOW TABLE STATUS LIKE 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 InnoDB # Compressed # # # # # # NULL # NULL NULL latin1_swedish_ci NULL row_format=COMPRESSED +DROP TABLE t1; +CREATE TABLE t1 (c1 INT) ENGINE=InnoDB page_compressed=1; +SHOW TABLE STATUS LIKE 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 InnoDB # Dynamic # # # # # # NULL # NULL NULL latin1_swedish_ci NULL `page_compressed`=1 +DROP TABLE IF EXISTS t1; +SET @save_format = @@GLOBAL.innodb_default_row_format; +SET GLOBAL innodb_default_row_format = redundant; +CREATE TABLE t1 (c1 INT) ENGINE=InnoDB; +SET GLOBAL innodb_default_row_format = @save_format; +TRUNCATE TABLE t1; +SHOW TABLE STATUS LIKE 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 InnoDB # Redundant # # # # # # NULL # NULL NULL latin1_swedish_ci NULL DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/default_row_format_create.test b/mysql-test/suite/innodb/t/default_row_format_create.test index e0981abf7eb..03a7ebd3752 100644 --- a/mysql-test/suite/innodb/t/default_row_format_create.test +++ b/mysql-test/suite/innodb/t/default_row_format_create.test @@ -22,7 +22,25 @@ SHOW TABLE STATUS LIKE 't1'; DROP TABLE t1; CREATE TABLE t1(c1 TEXT,c2 BLOB) ENGINE=InnoDB -ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; +ROW_FORMAT=COMPRESSED; +--replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 # 12 # +SHOW TABLE STATUS LIKE 't1'; +TRUNCATE TABLE t1; +--replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 # 12 # +SHOW TABLE STATUS LIKE 't1'; +DROP TABLE t1; + +--error 0,ER_CANT_CREATE_TABLE +CREATE TABLE t1 (c1 INT) ENGINE=InnoDB page_compressed=1; +--replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 # 12 # +SHOW TABLE STATUS LIKE 't1'; +DROP TABLE IF EXISTS t1; + +SET @save_format = @@GLOBAL.innodb_default_row_format; +SET GLOBAL innodb_default_row_format = redundant; +CREATE TABLE t1 (c1 INT) ENGINE=InnoDB; +SET GLOBAL innodb_default_row_format = @save_format; +TRUNCATE TABLE t1; --replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 # 12 # SHOW TABLE STATUS LIKE 't1'; DROP TABLE t1; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index b941ce8b825..319d6faedda 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -5580,6 +5580,25 @@ normalize_table_name_c_low( } } +create_table_info_t::create_table_info_t( + THD* thd, + TABLE* form, + HA_CREATE_INFO* create_info, + char* table_name, + char* remote_path, + bool file_per_table, + trx_t* trx) + : m_thd(thd), + m_trx(trx), + m_form(form), + m_default_row_format(innodb_default_row_format), + m_create_info(create_info), + m_table_name(table_name), m_drop_before_rollback(false), + m_remote_path(remote_path), + m_innodb_file_per_table(file_per_table) +{ +} + /** Normalizes a table name string. A normalized name consists of the database name catenated to '/' and table name. For example: test/mytable. @@ -11698,7 +11717,7 @@ Check engine specific table options not handled by SQL-parser. const char* create_table_info_t::check_table_options() { - enum row_type row_format = m_form->s->row_type; + enum row_type row_format = m_create_info->row_type; ha_table_option_struct *options= m_form->s->option_struct; fil_encryption_t encrypt = (fil_encryption_t)options->encryption; bool should_encrypt = (encrypt == FIL_ENCRYPTION_ON); @@ -11745,7 +11764,16 @@ create_table_info_t::check_table_options() return "PAGE_COMPRESSED"; } - if (row_format == ROW_TYPE_REDUNDANT) { + switch (row_format) { + default: + break; + case ROW_TYPE_DEFAULT: + if (m_default_row_format + != DEFAULT_ROW_FORMAT_REDUNDANT) { + break; + } + /* fall through */ + case ROW_TYPE_REDUNDANT: push_warning( m_thd, Sql_condition::WARN_LEVEL_WARN, HA_WRONG_CREATE_OPTION, @@ -11956,9 +11984,9 @@ create_table_info_t::parse_table_name( /** Determine InnoDB table flags. If strict_mode=OFF, this will adjust the flags to what should be assumed. -@retval true if successful, false if error */ -bool -create_table_info_t::innobase_table_flags() +@retval true on success +@retval false on error */ +bool create_table_info_t::innobase_table_flags() { DBUG_ENTER("innobase_table_flags"); @@ -11966,7 +11994,7 @@ create_table_info_t::innobase_table_flags() ulint zip_ssize = 0; enum row_type row_type; rec_format_t innodb_row_format = - get_row_format(innodb_default_row_format); + get_row_format(m_default_row_format); const bool is_temp = m_create_info->options & HA_LEX_CREATE_TMP_TABLE; bool zip_allowed @@ -12080,7 +12108,7 @@ index_bad: } } - row_type = m_form->s->row_type; + row_type = m_create_info->row_type; if (zip_ssize && zip_allowed) { /* if ROW_FORMAT is set to default, @@ -12420,8 +12448,6 @@ create_table_info_t::initialize() DBUG_RETURN(HA_ERR_WRONG_INDEX); } - ut_ad(m_form->s->row_type == m_create_info->row_type); - /* Get the transaction associated with the current thd, or create one if not yet created */ @@ -12465,8 +12491,6 @@ int create_table_info_t::prepare_create_table(const char* name, bool strict) ut_ad(m_thd != NULL); ut_ad(m_create_info != NULL); - ut_ad(m_form->s->row_type == m_create_info->row_type); - set_tablespace_type(false); normalize_table_name(m_table_name, name); @@ -13530,6 +13554,21 @@ int ha_innobase::truncate() trx_rollback_for_mysql(trx); row_mysql_unlock_data_dictionary(trx); } else { + switch (dict_tf_get_rec_format(ib_table->flags)) { + case REC_FORMAT_REDUNDANT: + info.row_type = ROW_TYPE_REDUNDANT; + break; + case REC_FORMAT_COMPACT: + info.row_type = ROW_TYPE_COMPACT; + break; + case REC_FORMAT_COMPRESSED: + info.row_type = ROW_TYPE_COMPRESSED; + break; + case REC_FORMAT_DYNAMIC: + info.row_type = ROW_TYPE_DYNAMIC; + break; + } + err = create(name, table, &info, ib_table->is_temporary() || dict_table_is_file_per_table(ib_table), trx); diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index b62045fd963..57c48f28ff7 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -641,15 +641,7 @@ public: char* table_name, char* remote_path, bool file_per_table, - trx_t* trx = NULL) - :m_thd(thd), - m_trx(trx), - m_form(form), - m_create_info(create_info), - m_table_name(table_name), m_drop_before_rollback(false), - m_remote_path(remote_path), - m_innodb_file_per_table(file_per_table) - {} + trx_t* trx = NULL); /** Initialize the object. */ int initialize(); @@ -758,6 +750,9 @@ private: /** Information on table columns and indexes. */ const TABLE* m_form; + /** Value of innodb_default_row_format */ + const ulong m_default_row_format; + /** Create options. */ HA_CREATE_INFO* m_create_info; diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index 337ded84f5f..a10bf769773 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -727,31 +727,30 @@ dict_tf_set( ulint page_compression_level, ulint not_used) { + *flags = use_data_dir ? 1 << DICT_TF_POS_DATA_DIR : 0; + switch (format) { case REC_FORMAT_REDUNDANT: - *flags = 0; ut_ad(zip_ssize == 0); - break; + /* no other options are allowed */ + ut_ad(!page_compressed); + return; case REC_FORMAT_COMPACT: - *flags = DICT_TF_COMPACT; + *flags |= DICT_TF_COMPACT; ut_ad(zip_ssize == 0); break; case REC_FORMAT_COMPRESSED: - *flags = DICT_TF_COMPACT + *flags |= DICT_TF_COMPACT | (1 << DICT_TF_POS_ATOMIC_BLOBS) | (zip_ssize << DICT_TF_POS_ZIP_SSIZE); break; case REC_FORMAT_DYNAMIC: - *flags = DICT_TF_COMPACT + *flags |= DICT_TF_COMPACT | (1 << DICT_TF_POS_ATOMIC_BLOBS); ut_ad(zip_ssize == 0); break; } - if (use_data_dir) { - *flags |= (1 << DICT_TF_POS_DATA_DIR); - } - if (page_compressed) { *flags |= (1 << DICT_TF_POS_ATOMIC_BLOBS) | (1 << DICT_TF_POS_PAGE_COMPRESSION)