From 78ea8ad425f2dc650b07e33d4724bbb21a9d1f17 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 10 Aug 2020 18:03:05 +0000 Subject: [PATCH 01/14] MDEV-23378 - fix an alleged memory "leak" in threadpool. Implement a workaround to shut the "memory not freed" message. --- sql/threadpool_generic.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sql/threadpool_generic.cc b/sql/threadpool_generic.cc index 02eb336facb..78b57340a6b 100644 --- a/sql/threadpool_generic.cc +++ b/sql/threadpool_generic.cc @@ -1084,7 +1084,10 @@ void thread_group_destroy(thread_group_t *thread_group) #endif if (my_atomic_add32(&shutdown_group_count, -1) == 1) + { my_free(all_groups); + all_groups= 0; + } } /** @@ -1677,6 +1680,14 @@ TP_pool_generic::~TP_pool_generic() { thread_group_close(&all_groups[i]); } + + /* + Wait until memory occupied by all_groups is freed. + */ + int timeout_ms=5000; + while(all_groups && timeout_ms--) + my_sleep(1000); + threadpool_started= false; DBUG_VOID_RETURN; } From caf105905af16a840c16cd4bc728f4b14bb76f1a Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 11 Aug 2020 10:33:10 +0400 Subject: [PATCH 02/14] Fixing sporading builtbot test failures happening at '00:00:00' sharp Some tests relied on the fact that DATETIME->DATE conversion always produce a truncation (with a warning). This is not the case when the SQL statement is executed at current time '00:00:00' sharp. Adding a new SET TIMESTAMP statements to make sure time is not '00:00:00'. --- mysql-test/r/type_date.result | 2 ++ mysql-test/r/type_datetime.result | 4 ++++ mysql-test/t/type_date.test | 6 ++++++ mysql-test/t/type_datetime.test | 5 +++++ 4 files changed, 17 insertions(+) diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result index 1a5a1d1c756..c945591fa07 100644 --- a/mysql-test/r/type_date.result +++ b/mysql-test/r/type_date.result @@ -429,6 +429,7 @@ select @a; # # BUG LP:1008487 virtual bool Item_cache::is_expensive(): Assertion `example' failed # +SET TIMESTAMP=UNIX_TIMESTAMP('2012-01-01 00:00:01'); create table t1(a date,key(a)); insert into t1 values ('2012-01-01'),('2012-02-02'); explain @@ -440,6 +441,7 @@ id select_type table type possible_keys key key_len ref rows Extra select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1; 1 drop table t1; +SET TIMESTAMP=DEFAULT; # # MDEV-9521 Least function returns 0000-00-00 for null date columns instead of null # MDEV-9972 Least function retuns date in date time format diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result index 3468ff67b53..26e852f116c 100644 --- a/mysql-test/r/type_datetime.result +++ b/mysql-test/r/type_datetime.result @@ -57,6 +57,7 @@ select * from t1; t 0000-00-00 00:00:00 drop table t1; +SET TIMESTAMP=UNIX_TIMESTAMP('2020-08-11 00:00:01'); CREATE TABLE t1 (a timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, b date, c time, d datetime); insert into t1 (b,c,d) values(now(),curtime(),now()); Warnings: @@ -65,6 +66,7 @@ select date_format(a,"%Y-%m-%d")=b,right(a+0,6)=c+0,a=d+0 from t1; date_format(a,"%Y-%m-%d")=b right(a+0,6)=c+0 a=d+0 1 1 1 drop table t1; +SET TIMESTAMP=DEFAULT; CREATE TABLE t1 (a datetime not null); insert into t1 values (0); select * from t1 where a is null; @@ -298,8 +300,10 @@ f2 f3 select f2 from t1 where DATE(f2) between "2001-4-15" AND "01-4-15"; f2 2001-04-15 00:00:00 +SET timestamp=UNIX_TIMESTAMP('2001-01-01 00:00:01'); SELECT 1 from dual where NOW() BETWEEN CURRENT_DATE() - INTERVAL 1 DAY AND CURRENT_DATE(); 1 +SET timestamp=DEFAULT; drop table t1; create table t1 (f1 date); insert into t1 values('01-01-01'),('01-01-02'),('01-01-03'); diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test index c86bc730392..91f4a8250f6 100644 --- a/mysql-test/t/type_date.test +++ b/mysql-test/t/type_date.test @@ -369,12 +369,18 @@ select @a; --echo # --echo # BUG LP:1008487 virtual bool Item_cache::is_expensive(): Assertion `example' failed --echo # + +# Set timestamp to make sure DATETIME->DATE truncation happens. +# Otherwise, the warning would disappear at '00:00:00' sharp, +# and a different execution plan would be chosen. +SET TIMESTAMP=UNIX_TIMESTAMP('2012-01-01 00:00:01'); create table t1(a date,key(a)); insert into t1 values ('2012-01-01'),('2012-02-02'); explain select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1; select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1; drop table t1; +SET TIMESTAMP=DEFAULT; --echo # --echo # MDEV-9521 Least function returns 0000-00-00 for null date columns instead of null diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test index 447a5d4b192..f2ef5030a6a 100644 --- a/mysql-test/t/type_datetime.test +++ b/mysql-test/t/type_datetime.test @@ -32,10 +32,12 @@ drop table t1; # Test insert of now() and curtime() # +SET TIMESTAMP=UNIX_TIMESTAMP('2020-08-11 00:00:01'); CREATE TABLE t1 (a timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, b date, c time, d datetime); insert into t1 (b,c,d) values(now(),curtime(),now()); select date_format(a,"%Y-%m-%d")=b,right(a+0,6)=c+0,a=d+0 from t1; drop table t1; +SET TIMESTAMP=DEFAULT; # # Test of datetime and not null @@ -201,6 +203,7 @@ drop table t1; # # Bug#16377: Wrong DATE/DATETIME comparison in BETWEEN function. # + create table t1 (f1 date, f2 datetime, f3 timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP); insert into t1 values('2001-01-01','2001-01-01 01:01:01','2001-01-01 01:01:01'); insert into t1 values('2001-02-05','2001-02-05 00:00:00','2001-02-05 01:01:01'); @@ -214,7 +217,9 @@ select f1, f2, f3 from t1 where cast(f1 as datetime) between f2 and select f2 from t1 where '2001-04-10 12:34:56' between f2 and '01-05-01'; select f2, f3 from t1 where '01-03-10' between f2 and f3; select f2 from t1 where DATE(f2) between "2001-4-15" AND "01-4-15"; +SET timestamp=UNIX_TIMESTAMP('2001-01-01 00:00:01'); SELECT 1 from dual where NOW() BETWEEN CURRENT_DATE() - INTERVAL 1 DAY AND CURRENT_DATE(); +SET timestamp=DEFAULT; drop table t1; # From 57d1a5fa8ed925b03d28aea3fab82de0823e68a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Mon, 10 Aug 2020 11:44:42 +0300 Subject: [PATCH 03/14] MDEV-22543 : Galera SST donation fails, FLUSH TABLES WITH READ LOCK times out During SST we need to let FTWRL to use normal timeout method even when client is disconnected. --- mysql-test/suite/galera/r/mdev-22543.result | 17 ++++++ mysql-test/suite/galera/t/mdev-22543.test | 58 +++++++++++++++++++++ sql/mdl.cc | 25 ++++++--- sql/wsrep_sst.cc | 13 ++++- sql/wsrep_sst.h | 2 + 5 files changed, 106 insertions(+), 9 deletions(-) create mode 100644 mysql-test/suite/galera/r/mdev-22543.result create mode 100644 mysql-test/suite/galera/t/mdev-22543.test diff --git a/mysql-test/suite/galera/r/mdev-22543.result b/mysql-test/suite/galera/r/mdev-22543.result new file mode 100644 index 00000000000..02f2b632b32 --- /dev/null +++ b/mysql-test/suite/galera/r/mdev-22543.result @@ -0,0 +1,17 @@ +connection node_1; +connection node_2; +connection node_1; +CREATE TABLE t1 (f1 INT PRIMARY KEY, f2 INT); +INSERT INTO t1 VALUES (1, 1); +SET DEBUG_SYNC = "before_lock_tables_takes_lock SIGNAL sync_point_reached WAIT_FOR sync_point_continue"; +UPDATE t1 SET f2 = 2 WHERE f1 = 1; +connection node_1_ctrl; +SET DEBUG_SYNC = "now WAIT_FOR sync_point_reached"; +connection node_2; +connection node_1_ctrl; +SET DEBUG_SYNC = "now SIGNAL sync_point_continue"; +connection node_1; +SET DEBUG_SYNC = "RESET"; +connection node_2; +connection node_1; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/mdev-22543.test b/mysql-test/suite/galera/t/mdev-22543.test new file mode 100644 index 00000000000..53662e36942 --- /dev/null +++ b/mysql-test/suite/galera/t/mdev-22543.test @@ -0,0 +1,58 @@ +# The test verifies that the FLUSH TABLES WITH READ LOCK does not +# time out if it needs to wait for another MDL lock for short duration +# during SST donation. + +--source include/galera_cluster.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +--let $node_1 = node_1 +--let $node_2 = node_2 +--source include/auto_increment_offset_save.inc + +--let $galera_connection_name = node_1_ctrl +--let $galera_server_number = 1 +--source include/galera_connect.inc + +# +# Run UPDATE on node_1 and make it block before table locks are taken. +# This should block FTWRL. +# +--connection node_1 +CREATE TABLE t1 (f1 INT PRIMARY KEY, f2 INT); +INSERT INTO t1 VALUES (1, 1); +SET DEBUG_SYNC = "before_lock_tables_takes_lock SIGNAL sync_point_reached WAIT_FOR sync_point_continue"; +--send UPDATE t1 SET f2 = 2 WHERE f1 = 1 + +--connection node_1_ctrl +SET DEBUG_SYNC = "now WAIT_FOR sync_point_reached"; + +# +# Restart node_2, force SST. +# +--connection node_2 +--source include/shutdown_mysqld.inc +--remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat +# Restart without waiting. The UPDATE should block FTWRL on node_1, +# so the SST cannot be completed and node_2 cannot join before +# UPDATE connection is signalled to continue. +--exec echo "restart:$start_mysqld_params" > $_expect_file_name +# If the bug is present, FTWRL times out on node_1 in couple of +# seconds and node_2 fails to join. +--sleep 10 + +--connection node_1_ctrl +SET DEBUG_SYNC = "now SIGNAL sync_point_continue"; + +--connection node_1 +--reap +SET DEBUG_SYNC = "RESET"; + +--connection node_2 +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection node_1 +DROP TABLE t1; + +--source include/auto_increment_offset_restore.inc diff --git a/sql/mdl.cc b/sql/mdl.cc index 9eeb82eeffd..14a1f17fe86 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -25,6 +25,7 @@ #include #include "wsrep_mysqld.h" #include "wsrep_thd.h" +#include "wsrep_sst.h" #ifdef HAVE_PSI_INTERFACE static PSI_mutex_key key_MDL_wait_LOCK_wait_status; @@ -2137,18 +2138,26 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout) wait_status= m_wait.timed_wait(m_owner, &abs_shortwait, FALSE, mdl_request->key.get_wait_state_name()); + THD* thd= m_owner->get_thd(); + if (wait_status != MDL_wait::EMPTY) break; /* Check if the client is gone while we were waiting. */ - if (! thd_is_connected(m_owner->get_thd())) + if (! thd_is_connected(thd)) { - /* - * The client is disconnected. Don't wait forever: - * assume it's the same as a wait timeout, this - * ensures all error handling is correct. - */ - wait_status= MDL_wait::TIMEOUT; - break; +#if defined(WITH_WSREP) && !defined(EMBEDDED_LIBRARY) + // During SST client might not be connected + if (!wsrep_is_sst_progress()) +#endif + { + /* + * The client is disconnected. Don't wait forever: + * assume it's the same as a wait timeout, this + * ensures all error handling is correct. + */ + wait_status= MDL_wait::TIMEOUT; + break; + } } mysql_prlock_wrlock(&lock->m_rwlock); diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 9472d66f4d3..a6accd52910 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -192,6 +192,7 @@ bool wsrep_before_SE() static bool sst_complete = false; static bool sst_needed = false; +static bool sst_in_progress = false; #define WSREP_EXTEND_TIMEOUT_INTERVAL 30 #define WSREP_TIMEDWAIT_SECONDS 10 @@ -1542,7 +1543,10 @@ static void* sst_donor_thread (void* a) char out_buf[out_len]; wsrep_uuid_t ret_uuid= WSREP_UUID_UNDEFINED; - wsrep_seqno_t ret_seqno= WSREP_SEQNO_UNDEFINED; // seqno of complete SST + // seqno of complete SST + wsrep_seqno_t ret_seqno= WSREP_SEQNO_UNDEFINED; + // SST is now in progress + sst_in_progress= true; wsp::thd thd(FALSE); // we turn off wsrep_on for this THD so that it can // operate with wsrep_ready == OFF @@ -1644,6 +1648,8 @@ wait_signal: wsrep->sst_sent (wsrep, &state_id, -err); proc.wait(); + sst_in_progress= false; + return NULL; } @@ -1818,3 +1824,8 @@ void wsrep_SE_initialized() { SE_initialized = true; } + +bool wsrep_is_sst_progress() +{ + return (sst_in_progress); +} diff --git a/sql/wsrep_sst.h b/sql/wsrep_sst.h index 063cab5f0f1..5a749d529fb 100644 --- a/sql/wsrep_sst.h +++ b/sql/wsrep_sst.h @@ -74,12 +74,14 @@ extern void wsrep_SE_init_grab(); /*! grab init critical section */ extern void wsrep_SE_init_wait(); /*! wait for SE init to complete */ extern void wsrep_SE_init_done(); /*! signal that SE init is complte */ extern void wsrep_SE_initialized(); /*! mark SE initialization complete */ +extern bool wsrep_is_sst_progress(); #else #define wsrep_SE_initialized() do { } while(0) #define wsrep_SE_init_grab() do { } while(0) #define wsrep_SE_init_done() do { } while(0) #define wsrep_sst_continue() (0) +#define wsrep_is_sst_progress() (0) #endif /* WITH_WSREP */ #endif /* WSREP_SST_H */ From 7ad4709a3b621c6fe56d653a2bb5018bf4234875 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Tue, 4 Aug 2020 14:25:58 +0200 Subject: [PATCH 04/14] MDEV-21526: mysqld_multi no longer works with different server binaries The problem is caused by the fact that adding the --defaults-group-suffix option to fix MDEV-18863 causes mysqld to read all options from the appropriate sections of the config file, including options specific to mysqld_multi. Reading unknown options (which are not supported by mysqld) causes mysqld to terminate with an error. However, the MDEV-18863 problem has been completely fixed by passing options on the command line, and now there is no need to specify the --defaults-group-suffix option (we just need to give priority to options passed through the command line, so as not to break MDEV-18863). --- scripts/mysqld_multi.sh | 14 +------------- scripts/wsrep_sst_mariabackup.sh | 25 +++++++++++++++++-------- scripts/wsrep_sst_rsync.sh | 8 +++++--- scripts/wsrep_sst_xtrabackup-v2.sh | 3 ++- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index 5f359551f0d..3aad68ffb6e 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -308,9 +308,7 @@ sub report_mysqlds sub start_mysqlds() { - my (@groups, $com, $tmp, $i, @options, $j, $mysqld_found, $suffix_found, $info_sent); - - $suffix_found= 0; + my (@groups, $com, $tmp, $i, @options, $j, $mysqld_found, $info_sent); if (!$opt_no_log) { @@ -349,10 +347,6 @@ sub start_mysqlds() $options[$j]= quote_shell_word($options[$j]); $tmp.= " $options[$j]"; } - elsif ("--defaults-group-suffix=" eq substr($options[$j], 0, 24)) - { - $suffix_found= 1; - } else { $options[$j]= quote_shell_word($options[$j]); @@ -369,12 +363,6 @@ sub start_mysqlds() $info_sent= 1; } - if (!$suffix_found) - { - $com.= " --defaults-group-suffix="; - $com.= substr($groups[$i],6); - } - $com.= $tmp; if ($opt_wsrep_new_cluster) { diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index a2d10beee06..2fce421e4eb 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -713,7 +713,8 @@ INNODB_DATA_HOME_DIR=${INNODB_DATA_HOME_DIR:-""} if [ ! -z "$INNODB_DATA_HOME_DIR_ARG" ]; then INNODB_DATA_HOME_DIR=$INNODB_DATA_HOME_DIR_ARG fi -# if INNODB_DATA_HOME_DIR env. variable is not set, try to get it from my.cnf +# if no command line arg and INNODB_DATA_HOME_DIR environment variable +# is not set, try to get it from my.cnf: if [ -z "$INNODB_DATA_HOME_DIR" ]; then INNODB_DATA_HOME_DIR=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-data-home-dir '') fi @@ -961,17 +962,25 @@ then ib_home_dir=$INNODB_DATA_HOME_DIR - # Try to set ib_log_dir from the command line: - ib_log_dir=$INNODB_LOG_GROUP_HOME_ARG - if [ -z "$ib_log_dir" ]; then - ib_log_dir=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-log-group-home-dir "") + WSREP_LOG_DIR=${WSREP_LOG_DIR:-""} + # Try to set WSREP_LOG_DIR from the command line: + if [ ! -z "$INNODB_LOG_GROUP_HOME_ARG" ]; then + WSREP_LOG_DIR=$INNODB_LOG_GROUP_HOME_ARG fi - if [ -z "$ib_log_dir" ]; then - ib_log_dir=$(parse_cnf --mysqld innodb-log-group-home-dir "") + # if no command line arg and WSREP_LOG_DIR is not set, + # try to get it from my.cnf: + if [ -z "$WSREP_LOG_DIR" ]; then + WSREP_LOG_DIR=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-log-group-home-dir '') + fi + if [ -z "$WSREP_LOG_DIR" ]; then + WSREP_LOG_DIR=$(parse_cnf --mysqld innodb-log-group-home-dir '') fi + ib_log_dir=$WSREP_LOG_DIR + # Try to set ib_undo_dir from the command line: - ib_undo_dir=$INNODB_UNDO_DIR_ARG + ib_undo_dir=${INNODB_UNDO_DIR_ARG:-""} + # if no command line arg then try to get it from my.cnf: if [ -z "$ib_undo_dir" ]; then ib_undo_dir=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-undo-directory "") fi diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 8fbb32135d7..890cd213b42 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -112,10 +112,11 @@ fi WSREP_LOG_DIR=${WSREP_LOG_DIR:-""} # Try to set WSREP_LOG_DIR from the command line: -if [ -z "$WSREP_LOG_DIR" ]; then +if [ ! -z "$INNODB_LOG_GROUP_HOME_ARG" ]; then WSREP_LOG_DIR=$INNODB_LOG_GROUP_HOME_ARG fi -# if WSREP_LOG_DIR env. variable is not set, try to get it from my.cnf +# if no command line arg and WSREP_LOG_DIR is not set, +# try to get it from my.cnf: if [ -z "$WSREP_LOG_DIR" ]; then WSREP_LOG_DIR=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-log-group-home-dir '') fi @@ -136,7 +137,8 @@ INNODB_DATA_HOME_DIR=${INNODB_DATA_HOME_DIR:-""} if [ ! -z "$INNODB_DATA_HOME_DIR_ARG" ]; then INNODB_DATA_HOME_DIR=$INNODB_DATA_HOME_DIR_ARG fi -# if INNODB_DATA_HOME_DIR env. variable is not set, try to get it from my.cnf +# if no command line arg and INNODB_DATA_HOME_DIR environment variable +# is not set, try to get it from my.cnf: if [ -z "$INNODB_DATA_HOME_DIR" ]; then INNODB_DATA_HOME_DIR=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-data-home-dir '') fi diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh index 75601e5c180..8fbbeda170c 100644 --- a/scripts/wsrep_sst_xtrabackup-v2.sh +++ b/scripts/wsrep_sst_xtrabackup-v2.sh @@ -904,7 +904,8 @@ INNODB_DATA_HOME_DIR=${INNODB_DATA_HOME_DIR:-""} if [ ! -z "$INNODB_DATA_HOME_DIR_ARG" ]; then INNODB_DATA_HOME_DIR=$INNODB_DATA_HOME_DIR_ARG fi -# if INNODB_DATA_HOME_DIR env. variable is not set, try to get it from my.cnf +# if no command line arg and INNODB_DATA_HOME_DIR environment variable +# is not set, try to get it from my.cnf: if [ -z "$INNODB_DATA_HOME_DIR" ]; then INNODB_DATA_HOME_DIR=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-data-home-dir '') fi From 31aef3ae99dff6b7154cf288b3dc508d367f19f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 11 Aug 2020 15:48:58 +0300 Subject: [PATCH 05/14] Fix GCC 10.2.0 -Og -Wmaybe-uninitialized For some reason, GCC emits more -Wmaybe-uninitialized warnings when using the flag -Og than when using -O2. Many of the warnings look genuine. --- extra/mariabackup/backup_copy.cc | 2 +- plugin/server_audit/server_audit.c | 62 ++++++++++++++++-------------- sql/item.cc | 4 +- sql/item_geofunc.cc | 17 ++++---- sql/mysqld.cc | 56 ++++++++++++--------------- sql/sql_time.cc | 2 +- storage/innobase/fts/fts0que.cc | 2 +- storage/maria/ma_create.c | 3 +- storage/maria/ma_loghandler.c | 3 +- storage/myisam/mi_create.c | 3 +- strings/ctype-ucs2.c | 2 +- 11 files changed, 78 insertions(+), 78 deletions(-) diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc index 6f9452ef76c..1cde4a4cf13 100644 --- a/extra/mariabackup/backup_copy.cc +++ b/extra/mariabackup/backup_copy.cc @@ -1786,7 +1786,7 @@ apply_log_finish() bool copy_back() { - bool ret; + bool ret = false; datadir_iter_t *it = NULL; datadir_node_t node; char *dst_dir; diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c index 8e468cf486d..1061c207a75 100644 --- a/plugin/server_audit/server_audit.c +++ b/plugin/server_audit/server_audit.c @@ -1428,7 +1428,6 @@ static size_t escape_string_hide_passwords(const char *str, unsigned int len, const char *res_start= result; const char *res_end= result + result_len - 2; size_t d_len; - char b_char; while (len) { @@ -1466,27 +1465,28 @@ static size_t escape_string_hide_passwords(const char *str, unsigned int len, if (*next_s) { - memmove(result + d_len, "*****", 5); + const char b_char= *next_s++; + memset(result + d_len, '*', 5); result+= d_len + 5; - b_char= *(next_s++); + + while (*next_s) + { + if (*next_s == b_char) + { + ++next_s; + break; + } + if (*next_s == '\\') + { + if (next_s[1]) + next_s++; + } + next_s++; + } } else result+= d_len; - while (*next_s) - { - if (*next_s == b_char) - { - ++next_s; - break; - } - if (*next_s == '\\') - { - if (next_s[1]) - next_s++; - } - next_s++; - } len-= (uint)(next_s - str); str= next_s; continue; @@ -1494,19 +1494,23 @@ static size_t escape_string_hide_passwords(const char *str, unsigned int len, no_password: if (result >= res_end) break; - if ((b_char= escaped_char(*str))) - { - if (result+1 >= res_end) - break; - *(result++)= '\\'; - *(result++)= b_char; - } - else if (is_space(*str)) - *(result++)= ' '; else - *(result++)= *str; - str++; - len--; + { + const char b_char= escaped_char(*str); + if (b_char) + { + if (result+1 >= res_end) + break; + *(result++)= '\\'; + *(result++)= b_char; + } + else if (is_space(*str)) + *(result++)= ' '; + else + *(result++)= *str; + str++; + len--; + } } *result= 0; return result - res_start; diff --git a/sql/item.cc b/sql/item.cc index 140eb5244ec..e001178f8b6 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2018, Oracle and/or its affiliates. - Copyright (c) 2010, 2018, MariaDB Corporation + Copyright (c) 2010, 2020, 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 @@ -7212,7 +7212,6 @@ Item *find_producing_item(Item *item, st_select_lex *sel) DBUG_ASSERT(item->type() == Item::FIELD_ITEM || (item->type() == Item::REF_ITEM && ((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF)); - Item *producing_item; Item_field *field_item= NULL; Item_equal *item_equal= item->get_item_equal(); table_map tab_map= sel->master_unit()->derived->table->map; @@ -7234,6 +7233,7 @@ Item *find_producing_item(Item *item, st_select_lex *sel) List_iterator_fast li(sel->item_list); if (field_item) { + Item *producing_item= NULL; uint field_no= field_item->field->field_index; for (uint i= 0; i <= field_no; i++) producing_item= li++; diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 645a3668ed8..0db8d7075f6 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -2389,12 +2389,15 @@ double Item_func_distance::val_real() MBR mbr1, mbr2; const char *c_end; - - if ((null_value= (args[0]->null_value || args[1]->null_value || - !(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) || - !(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())) || - g1->get_mbr(&mbr1, &c_end) || - g2->get_mbr(&mbr2, &c_end)))) + if (args[0]->null_value || args[1]->null_value) + goto mem_error; + g1= Geometry::construct(&buffer1, res1->ptr(), res1->length()); + if (!g1) + goto mem_error; + g2= Geometry::construct(&buffer2, res2->ptr(), res2->length()); + if (!g2) + goto mem_error; + if (g1->get_mbr(&mbr1, &c_end) || g2->get_mbr(&mbr2, &c_end)) goto mem_error; mbr1.add_mbr(&mbr2); @@ -2543,7 +2546,7 @@ String *Item_func_pointonsurface::val_str(String *str) Geometry *g; MBR mbr; const char *c_end; - double UNINIT_VAR(px), UNINIT_VAR(py), x0, y0; + double UNINIT_VAR(px), UNINIT_VAR(py), x0, UNINIT_VAR(y0); String *result= 0; const Gcalc_scan_iterator::point *pprev= NULL; uint32 srid; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 44f8558e474..5991ef5f7b0 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -6620,13 +6620,11 @@ void handle_connections_sockets() MYSQL_SOCKET sock= mysql_socket_invalid(); MYSQL_SOCKET new_sock= mysql_socket_invalid(); uint error_count=0; - CONNECT *connect; struct sockaddr_storage cAddr; int ip_flags __attribute__((unused))=0; int socket_flags __attribute__((unused))= 0; int extra_ip_flags __attribute__((unused))=0; int flags=0,retval; - bool is_unix_sock; #ifdef HAVE_POLL int socket_count= 0; struct pollfd fds[3]; // for ip_sock, unix_sock and extra_ip_sock @@ -6826,41 +6824,37 @@ void handle_connections_sockets() DBUG_PRINT("info", ("Creating CONNECT for new connection")); - if ((connect= new CONNECT())) + if (CONNECT *connect= new CONNECT()) { - is_unix_sock= (mysql_socket_getfd(sock) == - mysql_socket_getfd(unix_sock)); + const bool is_unix_sock= (mysql_socket_getfd(sock) == + mysql_socket_getfd(unix_sock)); - if (!(connect->vio= - mysql_socket_vio_new(new_sock, - is_unix_sock ? VIO_TYPE_SOCKET : - VIO_TYPE_TCPIP, - is_unix_sock ? VIO_LOCALHOST: 0))) + if ((connect->vio= + mysql_socket_vio_new(new_sock, + is_unix_sock ? VIO_TYPE_SOCKET : + VIO_TYPE_TCPIP, + is_unix_sock ? VIO_LOCALHOST: 0))) { - delete connect; - connect= 0; // Error handling below + if (is_unix_sock) + connect->host= my_localhost; + + if (mysql_socket_getfd(sock) == mysql_socket_getfd(extra_ip_sock)) + { + connect->extra_port= 1; + connect->scheduler= extra_thread_scheduler; + } + create_new_thread(connect); + continue; } + + delete connect; } - if (!connect) - { - /* Connect failure */ - (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); - (void) mysql_socket_close(new_sock); - statistic_increment(aborted_connects,&LOCK_status); - statistic_increment(connection_errors_internal, &LOCK_status); - continue; - } - - if (is_unix_sock) - connect->host= my_localhost; - - if (mysql_socket_getfd(sock) == mysql_socket_getfd(extra_ip_sock)) - { - connect->extra_port= 1; - connect->scheduler= extra_thread_scheduler; - } - create_new_thread(connect); + /* Connect failure */ + (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); + (void) mysql_socket_close(new_sock); + statistic_increment(aborted_connects,&LOCK_status); + statistic_increment(connection_errors_internal, &LOCK_status); } sd_notify(0, "STOPPING=1\n" "STATUS=Shutdown in progress\n"); diff --git a/sql/sql_time.cc b/sql/sql_time.cc index 7f5919007e8..b92b35a3abb 100644 --- a/sql/sql_time.cc +++ b/sql/sql_time.cc @@ -358,7 +358,7 @@ static bool number_to_time_with_warn(bool neg, ulonglong nr, ulong sec_part, int was_cut; longlong res; enum_field_types f_type; - bool have_warnings; + bool have_warnings= false; if (fuzzydate & TIME_TIME_ONLY) { diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc index 81018f57619..6396dad4aa5 100644 --- a/storage/innobase/fts/fts0que.cc +++ b/storage/innobase/fts/fts0que.cc @@ -2742,7 +2742,7 @@ fts_query_phrase_search( /* Ignore empty strings. */ if (num_token > 0) { - fts_string_t* token; + fts_string_t* token = NULL; fts_fetch_t fetch; trx_t* trx = query->trx; fts_ast_oper_t oper = query->oper; diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c index 2c9c15d8a2a..bca7ad94f85 100644 --- a/storage/maria/ma_create.c +++ b/storage/maria/ma_create.c @@ -75,7 +75,7 @@ int maria_create(const char *name, enum data_file_type datafile_type, uint max_field_lengths, extra_header_size, column_nr; uint internal_table= flags & HA_CREATE_INTERNAL_TABLE; ulong reclength, real_reclength,min_pack_length; - char kfilename[FN_REFLEN], klinkname[FN_REFLEN], *klinkname_ptr; + char kfilename[FN_REFLEN], klinkname[FN_REFLEN], *klinkname_ptr= NullS; char dfilename[FN_REFLEN], dlinkname[FN_REFLEN], *dlinkname_ptr= 0; ulong pack_reclength; ulonglong tot_length,max_rows, tmp; @@ -889,7 +889,6 @@ int maria_create(const char *name, enum data_file_type datafile_type, fn_format(kfilename, name, "", MARIA_NAME_IEXT, MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH | (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT)); - klinkname_ptr= NullS; /* Replace the current file. Don't sync dir now if the data file has the same path. diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index 9fe746a167b..b98fbe29e1f 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -3614,7 +3614,8 @@ my_bool translog_init_with_table(const char *directory, int old_log_was_recovered= 0, logs_found= 0; uint old_flags= flags; uint32 start_file_num= 1; - TRANSLOG_ADDRESS sure_page, last_page, last_valid_page, checkpoint_lsn; + TRANSLOG_ADDRESS UNINIT_VAR(sure_page), last_page, last_valid_page, + checkpoint_lsn; my_bool version_changed= 0; DBUG_ENTER("translog_init_with_table"); diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c index fd230698acc..9f17a9b2de9 100644 --- a/storage/myisam/mi_create.c +++ b/storage/myisam/mi_create.c @@ -46,7 +46,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, uint aligned_key_start, block_length, res; uint internal_table= flags & HA_CREATE_INTERNAL_TABLE; ulong reclength, real_reclength,min_pack_length; - char kfilename[FN_REFLEN],klinkname[FN_REFLEN], *klinkname_ptr; + char kfilename[FN_REFLEN],klinkname[FN_REFLEN], *klinkname_ptr= 0; char dfilename[FN_REFLEN],dlinkname[FN_REFLEN], *dlinkname_ptr= 0; ulong pack_reclength; ulonglong tot_length,max_rows, tmp; @@ -622,7 +622,6 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, fn_format(kfilename, name, "", MI_NAME_IEXT, MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH | (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT)); - klinkname_ptr= 0; /* Replace the current file */ create_flag=(flags & HA_CREATE_KEEP_FILES) ? 0 : MY_DELETE_OLD; } diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index f229bbf7323..c5182911c4a 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -827,7 +827,7 @@ my_strtoll10_mb2(CHARSET_INFO *cs __attribute__((unused)), const char *nptr, char **endptr, int *error) { const uchar *s, *end, *start, *n_end, *true_end; - uchar c; + uchar UNINIT_VAR(c); unsigned long i, j, k; ulonglong li; int negative; From de8d57e5220ccfab31db4da86167f441df78869b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 11 Aug 2020 15:49:37 +0300 Subject: [PATCH 06/14] MDEV-23447 SIGSEGV in fil_system_t::keyrotate_next() fil_system_t::keyrotate_next(): If space && space->is_in_rotation_list does not hold, iterate from the start of the list. In debug builds, we would typically have hit SIGSEGV because the iterator would have wrapped a null pointer. It might also be that we are dereferencing a stale pointer. There is no test case, because the encryption is very nondeterministic in nature, due to the use of background threads. This scenario can be hit by setting the following: SET GLOBAL innodb_encryption_threads=5; SET GLOBAL innodb_encryption_rotate_key_age=0; --- storage/innobase/fil/fil0crypt.cc | 35 ++++++++++++++++++------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index c687c53ac14..09f2730edec 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -1388,29 +1388,34 @@ the encryption parameters were changed inline fil_space_t *fil_system_t::keyrotate_next(fil_space_t *space, bool recheck, bool encrypt) { - ut_ad(mutex_own(&fil_system->mutex)); + ut_ad(mutex_own(&mutex)); sized_ilist::iterator it= - space ? space : fil_system->rotation_list.begin(); + space && space->is_in_rotation_list ? space : rotation_list.begin(); const sized_ilist::iterator end= - fil_system->rotation_list.end(); + rotation_list.end(); if (space) { - while (++it != end && (!UT_LIST_GET_LEN(it->chain) || it->is_stopping())); + const bool released= !--space->n_pending_ops; - /* If one of the encryption threads already started the encryption - of the table then don't remove the unencrypted spaces from rotation list - - If there is a change in innodb_encrypt_tables variables value then - don't remove the last processed tablespace from the rotation list. */ - if (!--space->n_pending_ops && - (!recheck || space->crypt_data) && !encrypt == !srv_encrypt_tables && - space->is_in_rotation_list) + if (space->is_in_rotation_list) { - ut_a(!fil_system->rotation_list.empty()); - fil_system->rotation_list.remove(*space); - space->is_in_rotation_list= false; + while (++it != end && + (!UT_LIST_GET_LEN(it->chain) || it->is_stopping())); + + /* If one of the encryption threads already started the encryption + of the table then don't remove the unencrypted spaces from rotation list + + If there is a change in innodb_encrypt_tables variables value then + don't remove the last processed tablespace from the rotation list. */ + if (released && (!recheck || space->crypt_data) && + !encrypt == !srv_encrypt_tables) + { + ut_a(!rotation_list.empty()); + rotation_list.remove(*space); + space->is_in_rotation_list= false; + } } } From c96be848d3bbb668d27645c36ca66c697fdc2752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 11 Aug 2020 18:52:38 +0300 Subject: [PATCH 07/14] MDEV-14119 Assertion cmp_rec_rec() in ALTER TABLE innobase_pk_order_preserved(): Treat an added AUTO_INCREMENT column in the same way as an added existing column. In either case, the column values are not guaranteed to be constant, and thus the ordering may change if such a column is added before any existing PRIMARY KEY columns. prepare_inplace_alter_table_dict(): Initialize dict_table_t::persistent_autoinc before invoking innobase_pk_order_preserved(). --- .../innodb/include/alter_table_pk_no_sort.inc | 7 +++++++ mysql-test/suite/innodb/r/alter_table.result | 7 +++++++ .../suite/innodb/r/innodb-index-debug.result | 5 +++++ mysql-test/suite/innodb/r/innodb-index.result | 5 +++++ mysql-test/suite/innodb/t/alter_table.test | 9 +++++++++ storage/innobase/handler/handler0alter.cc | 18 +++++++++++------- 6 files changed, 44 insertions(+), 7 deletions(-) diff --git a/mysql-test/suite/innodb/include/alter_table_pk_no_sort.inc b/mysql-test/suite/innodb/include/alter_table_pk_no_sort.inc index 6a2fcd15be0..61e304a7626 100644 --- a/mysql-test/suite/innodb/include/alter_table_pk_no_sort.inc +++ b/mysql-test/suite/innodb/include/alter_table_pk_no_sort.inc @@ -263,3 +263,10 @@ create table t1(o1 int, o2 int, o3 int, primary key(o1,o2,o3)) engine = innodb; insert into t1 values(1,1,2),(2,2,1); alter table t1 drop primary key, add primary key(o1), lock=none; drop table t1; + +# pk(o1,o2) to pk(o1,o2,autoinc) must not sort +create table t1(o1 int, o2 int, primary key(o1,o2)) engine = innodb; +insert into t1 values(1,1),(2,1); +alter table t1 drop primary key, add column a int unique auto_increment, +add primary key(o1,o2,a), algorithm=inplace; +drop table t1; diff --git a/mysql-test/suite/innodb/r/alter_table.result b/mysql-test/suite/innodb/r/alter_table.result index e47bfb90152..94262ac29c3 100644 --- a/mysql-test/suite/innodb/r/alter_table.result +++ b/mysql-test/suite/innodb/r/alter_table.result @@ -53,3 +53,10 @@ ALTER TABLE t1 DROP a; ERROR HY000: Cannot drop index 'a': needed in a foreign key constraint ALTER TABLE t1 ADD c INT; DROP TABLE t1, tx; +# +# MDEV-14119 Assertion cmp_rec_rec() on ALTER TABLE +# +CREATE TABLE t1(a INT NOT NULL UNIQUE) ENGINE=InnoDB; +INSERT INTO t1 SELECT * FROM seq_1_to_128; +ALTER TABLE t1 ADD b TINYINT AUTO_INCREMENT PRIMARY KEY, DROP KEY a; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/innodb-index-debug.result b/mysql-test/suite/innodb/r/innodb-index-debug.result index b1f8c9ad3cc..bf2abce989c 100644 --- a/mysql-test/suite/innodb/r/innodb-index-debug.result +++ b/mysql-test/suite/innodb/r/innodb-index-debug.result @@ -323,4 +323,9 @@ create table t1(o1 int, o2 int, o3 int, primary key(o1,o2,o3)) engine = innodb; insert into t1 values(1,1,2),(2,2,1); alter table t1 drop primary key, add primary key(o1), lock=none; drop table t1; +create table t1(o1 int, o2 int, primary key(o1,o2)) engine = innodb; +insert into t1 values(1,1),(2,1); +alter table t1 drop primary key, add column a int unique auto_increment, +add primary key(o1,o2,a), algorithm=inplace; +drop table t1; SET DEBUG_DBUG = @saved_debug_dbug; diff --git a/mysql-test/suite/innodb/r/innodb-index.result b/mysql-test/suite/innodb/r/innodb-index.result index bdc16ad7692..5e91efb7062 100644 --- a/mysql-test/suite/innodb/r/innodb-index.result +++ b/mysql-test/suite/innodb/r/innodb-index.result @@ -1903,6 +1903,11 @@ create table t1(o1 int, o2 int, o3 int, primary key(o1,o2,o3)) engine = innodb; insert into t1 values(1,1,2),(2,2,1); alter table t1 drop primary key, add primary key(o1), lock=none; drop table t1; +create table t1(o1 int, o2 int, primary key(o1,o2)) engine = innodb; +insert into t1 values(1,1),(2,1); +alter table t1 drop primary key, add column a int unique auto_increment, +add primary key(o1,o2,a), algorithm=inplace; +drop table t1; # # MDEV-15325 Incomplete validation of missing tablespace during recovery # diff --git a/mysql-test/suite/innodb/t/alter_table.test b/mysql-test/suite/innodb/t/alter_table.test index d0943e7d407..6bc30d2e8ee 100644 --- a/mysql-test/suite/innodb/t/alter_table.test +++ b/mysql-test/suite/innodb/t/alter_table.test @@ -1,4 +1,5 @@ --source include/have_innodb.inc +--source include/have_sequence.inc # # MDEV-11995 ALTER TABLE proceeds despite reporting ER_TOO_LONG_KEY error # @@ -59,3 +60,11 @@ ALTER TABLE t1 ADD b INT; ALTER TABLE t1 DROP a; ALTER TABLE t1 ADD c INT; DROP TABLE t1, tx; + +--echo # +--echo # MDEV-14119 Assertion cmp_rec_rec() on ALTER TABLE +--echo # +CREATE TABLE t1(a INT NOT NULL UNIQUE) ENGINE=InnoDB; +INSERT INTO t1 SELECT * FROM seq_1_to_128; +ALTER TABLE t1 ADD b TINYINT AUTO_INCREMENT PRIMARY KEY, DROP KEY a; +DROP TABLE t1; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 782b0d9efb2..0f5ac81f663 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -3362,7 +3362,11 @@ innobase_pk_order_preserved( if (old_pk_column) { new_field_order = old_field; } else if (innobase_pk_col_is_existing(new_col_no, col_map, - old_n_cols)) { + old_n_cols) + || new_clust_index->table->persistent_autoinc + == new_field + 1) { + /* Adding an existing column or an AUTO_INCREMENT + column may change the existing ordering. */ new_field_order = old_n_uniq + existing_field_count++; } else { /* Skip newly added column. */ @@ -4913,12 +4917,6 @@ index_created: user_table); dict_index_t* new_clust_index = dict_table_get_first_index( ctx->new_table); - ctx->skip_pk_sort = innobase_pk_order_preserved( - ctx->col_map, clust_index, new_clust_index); - - DBUG_EXECUTE_IF("innodb_alter_table_pk_assert_no_sort", - DBUG_ASSERT(ctx->skip_pk_sort);); - DBUG_ASSERT(!ctx->new_table->persistent_autoinc); if (const Field* ai = altered_table->found_next_number_field) { const unsigned col_no = innodb_col_no(ai); @@ -4937,6 +4935,12 @@ index_created: } } + ctx->skip_pk_sort = innobase_pk_order_preserved( + ctx->col_map, clust_index, new_clust_index); + + DBUG_EXECUTE_IF("innodb_alter_table_pk_assert_no_sort", + DBUG_ASSERT(ctx->skip_pk_sort);); + if (ctx->online) { /* Allocate a log for online table rebuild. */ rw_lock_x_lock(&clust_index->lock); From 01738d08f30315f10c14faa605d0087e54156cd0 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Tue, 11 Aug 2020 20:12:30 +0300 Subject: [PATCH 08/14] add debug assertion to ilist --- include/ilist.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/ilist.h b/include/ilist.h index 722677f9057..4b89efe7717 100644 --- a/include/ilist.h +++ b/include/ilist.h @@ -26,8 +26,7 @@ template struct ilist_node { ilist_node() #ifndef DBUG_OFF - : - next(NULL), prev(NULL) + : next(NULL), prev(NULL) #endif { } @@ -70,11 +69,12 @@ public: typedef T *pointer; typedef T &reference; - Iterator(ListNode *node) : node_(node) {} + Iterator(ListNode *node) : node_(node) { assert(node_); } Iterator &operator++() { node_= node_->next; + assert(node_); return *this; } Iterator operator++(int) @@ -87,6 +87,7 @@ public: Iterator &operator--() { node_= node_->prev; + assert(node_); return *this; } Iterator operator--(int) From 5a4ae142f48bcf9e11becfd4c98d72de338bba6a Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Wed, 12 Aug 2020 10:24:09 +0300 Subject: [PATCH 09/14] replace assert() with DBUG_ASSERT() --- include/ilist.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/ilist.h b/include/ilist.h index 4b89efe7717..dc75d6907ce 100644 --- a/include/ilist.h +++ b/include/ilist.h @@ -18,6 +18,8 @@ #pragma once +#include "my_dbug.h" + #include #include @@ -69,12 +71,12 @@ public: typedef T *pointer; typedef T &reference; - Iterator(ListNode *node) : node_(node) { assert(node_); } + Iterator(ListNode *node) : node_(node) { DBUG_ASSERT(node_); } Iterator &operator++() { node_= node_->next; - assert(node_); + DBUG_ASSERT(node_); return *this; } Iterator operator++(int) @@ -87,7 +89,7 @@ public: Iterator &operator--() { node_= node_->prev; - assert(node_); + DBUG_ASSERT(node_); return *this; } Iterator operator--(int) From 4387e3a13bba61313a1637f63253e01e6edbce0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 12 Aug 2020 13:08:17 +0300 Subject: [PATCH 10/14] Use DBUG_ASSERT(ptr != NULL) to ease merging to 10.3 In 10.3, DBUG_ASSERT() may expand to something that includes __builtin_expect(), which expects integer arguments, not pointers. To avoid any compiler warnings, let us use an explicit rather than implicit comparison to the null pointer. --- include/ilist.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/ilist.h b/include/ilist.h index dc75d6907ce..ed1d978a0d6 100644 --- a/include/ilist.h +++ b/include/ilist.h @@ -71,12 +71,12 @@ public: typedef T *pointer; typedef T &reference; - Iterator(ListNode *node) : node_(node) { DBUG_ASSERT(node_); } + Iterator(ListNode *node) : node_(node) { DBUG_ASSERT(node_ != NULL); } Iterator &operator++() { node_= node_->next; - DBUG_ASSERT(node_); + DBUG_ASSERT(node_ != NULL); return *this; } Iterator operator++(int) From 18f374cb20a8d3ec8d8349be40a8659d18ee7678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 12 Aug 2020 13:12:51 +0300 Subject: [PATCH 11/14] MDEV-23439 Assertion size == space->size failed in buf_read_ahead_random The debug assertion is bogus, and we had removed it in commit b1ab211dee599eabd9a5b886fafa3adea29ae041 (MDEV-15053) in the MariaDB Server 10.5 branch. For a small data file, fil_space_extend_must_retry() would always allocate a minimum size of 4*innodb_page_size. It is possible that random read-ahead will be triggered for a smaller file than this. In the observed case, the read-ahead was triggered for a 6-page file that used ROW_FORMAT=COMPRESSED with 8KiB page size. So, the desired file size was 49152 bytes, but the actual size was 65536 bytes. --- storage/innobase/buf/buf0rea.cc | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc index d6f096fc80e..ad583e577c4 100644 --- a/storage/innobase/buf/buf0rea.cc +++ b/storage/innobase/buf/buf0rea.cc @@ -280,23 +280,6 @@ buf_read_ahead_random( * buf_read_ahead_random_area; if (fil_space_t* space = fil_space_acquire(page_id.space())) { -#ifdef UNIV_DEBUG - if (srv_file_per_table) { - ulint size = 0; - - for (const fil_node_t* node = - UT_LIST_GET_FIRST(space->chain); - node != NULL; - node = UT_LIST_GET_NEXT(chain, node)) { - - size += ulint(os_file_get_size(node->handle) - / page_size.physical()); - } - - ut_ad(size == space->size); - } -#endif /* UNIV_DEBUG */ - high = space->max_page_number_for_io(high); fil_space_release(space); } else { From efd8af535a4fa4aa3dd89a325340b6eb648e1bc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 12 Aug 2020 18:21:53 +0300 Subject: [PATCH 12/14] MDEV-19526 heap number overflow on innodb_page_size=64k InnoDB only reserves 13 bits for the heap number in the record header, limiting the heap number to be at most 8191. But, when using innodb_page_size=64k and secondary index records of 7 bytes each, it is possible to exceed the maximum heap number. btr_cur_optimistic_insert(): Let the operation fail if the maximum number of records would be exceeded. page_mem_alloc_heap(): Move to the same compilation unit with the only caller, and let the operation fail if the maximum heap number has been allocated already. --- mysql-test/suite/innodb/r/innodb-64k.result | 7 +++ mysql-test/suite/innodb/t/innodb-64k.test | 10 +++++ storage/innobase/btr/btr0cur.cc | 18 +++++--- storage/innobase/include/page0page.h | 17 +------- storage/innobase/page/page0cur.cc | 47 +++++++++++++++++++++ storage/innobase/page/page0page.cc | 40 +----------------- storage/xtradb/btr/btr0cur.cc | 18 +++++--- storage/xtradb/include/page0page.h | 17 +------- storage/xtradb/page/page0cur.cc | 47 +++++++++++++++++++++ storage/xtradb/page/page0page.cc | 40 +----------------- 10 files changed, 139 insertions(+), 122 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-64k.result b/mysql-test/suite/innodb/r/innodb-64k.result index dc938f236cd..0ecc1b7096b 100644 --- a/mysql-test/suite/innodb/r/innodb-64k.result +++ b/mysql-test/suite/innodb/r/innodb-64k.result @@ -1084,3 +1084,10 @@ update t2 set col145=@b; COMMIT; drop table t2; DROP TABLE t1; +# +# MDEV-19526 heap number overflow +# +CREATE TABLE t1(a SMALLINT NOT NULL UNIQUE AUTO_INCREMENT, KEY(a)) +ENGINE=InnoDB; +INSERT INTO t1 (a) SELECT seq FROM seq_1_to_8191; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/innodb-64k.test b/mysql-test/suite/innodb/t/innodb-64k.test index 0498544279b..50dc1535aa6 100644 --- a/mysql-test/suite/innodb/t/innodb-64k.test +++ b/mysql-test/suite/innodb/t/innodb-64k.test @@ -2,6 +2,7 @@ # Tests for setting innodb-page-size=64k; --source include/have_innodb.inc --source include/have_innodb_64k.inc +--source include/have_sequence.inc call mtr.add_suppression("InnoDB: Warning: innodb_page_size has been changed from default value *"); call mtr.add_suppression("InnoDB: Resizing redo log from *"); @@ -650,6 +651,15 @@ COMMIT; drop table t2; DROP TABLE t1; + +--echo # +--echo # MDEV-19526 heap number overflow +--echo # +CREATE TABLE t1(a SMALLINT NOT NULL UNIQUE AUTO_INCREMENT, KEY(a)) +ENGINE=InnoDB; +INSERT INTO t1 (a) SELECT seq FROM seq_1_to_8191; +DROP TABLE t1; + # # restore environment to the state it was before this test execution # diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 7b2fbfa0f0e..8e1a7200ab3 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -3,7 +3,7 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2015, 2017, MariaDB Corporation. +Copyright (c) 2015, 2020, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1433,17 +1433,23 @@ fail_err: } ulint max_size = page_get_max_insert_size_after_reorganize(page, 1); + if (max_size < rec_size) { + goto fail; + } + + const ulint n_recs = page_get_n_recs(page); + if (UNIV_UNLIKELY(n_recs >= 8189)) { + ut_ad(srv_page_size == 65536); + goto fail; + } if (page_has_garbage(page)) { - if ((max_size < rec_size - || max_size < BTR_CUR_PAGE_REORGANIZE_LIMIT) - && page_get_n_recs(page) > 1 + if (max_size < BTR_CUR_PAGE_REORGANIZE_LIMIT + && n_recs > 1 && page_get_max_insert_size(page, 1) < rec_size) { goto fail; } - } else if (max_size < rec_size) { - goto fail; } /* If there have been many consecutive inserts to the diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h index 64ae31905b4..5e9081476ce 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, 2018, MariaDB Corporation. +Copyright (c) 2013, 2020, 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 @@ -759,21 +759,6 @@ page_mem_alloc_free( free record list */ ulint need); /*!< in: number of bytes allocated */ /************************************************************//** -Allocates a block of memory from the heap of an index page. -@return pointer to start of allocated buffer, or NULL if allocation fails */ -UNIV_INTERN -byte* -page_mem_alloc_heap( -/*================*/ - page_t* page, /*!< in/out: index page */ - page_zip_des_t* page_zip,/*!< in/out: compressed page with enough - space available for inserting the record, - or NULL */ - ulint need, /*!< in: total number of bytes needed */ - ulint* heap_no);/*!< out: this contains the heap number - of the allocated record - if allocation succeeds */ -/************************************************************//** Puts a record to free list. */ UNIV_INLINE void diff --git a/storage/innobase/page/page0cur.cc b/storage/innobase/page/page0cur.cc index e9ac4b4bb04..94e861ab554 100644 --- a/storage/innobase/page/page0cur.cc +++ b/storage/innobase/page/page0cur.cc @@ -2,6 +2,7 @@ Copyright (c) 1994, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2020, 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 @@ -941,6 +942,52 @@ page_cur_parse_insert_rec( return(ptr + end_seg_len); } +/************************************************************//** +Allocates a block of memory from the heap of an index page. +@return pointer to start of allocated buffer, or NULL if allocation fails */ +static +byte* +page_mem_alloc_heap( +/*================*/ + page_t* page, /*!< in/out: index page */ + page_zip_des_t* page_zip,/*!< in/out: compressed page with enough + space available for inserting the record, + or NULL */ + ulint need, /*!< in: total number of bytes needed */ + ulint* heap_no)/*!< out: this contains the heap number + of the allocated record + if allocation succeeds */ +{ + byte* block; + ulint avl_space; + + ut_ad(page && heap_no); + + avl_space = page_get_max_insert_size(page, 1); + + if (avl_space >= need) { + const ulint h = page_dir_get_n_heap(page); + if (UNIV_UNLIKELY(h >= 8191)) { + /* At the minimum record size of 5+2 bytes, + we can only reach this condition when using + innodb_page_size=64k. */ + ut_ad(srv_page_size == 65536); + return(NULL); + } + *heap_no = h; + + block = page_header_get_ptr(page, PAGE_HEAP_TOP); + + page_header_set_ptr(page, page_zip, PAGE_HEAP_TOP, + block + need); + page_dir_set_n_heap(page, page_zip, 1 + *heap_no); + + return(block); + } + + return(NULL); +} + /***********************************************************//** Inserts a record next to page cursor on an uncompressed page. Returns pointer to inserted record if succeed, i.e., enough diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index ac16d71322a..1d9e4a97782 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -2,7 +2,7 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2018, MariaDB Corporation. +Copyright (c) 2018, 2020, 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 @@ -235,44 +235,6 @@ page_set_max_trx_id( } } -/************************************************************//** -Allocates a block of memory from the heap of an index page. -@return pointer to start of allocated buffer, or NULL if allocation fails */ -UNIV_INTERN -byte* -page_mem_alloc_heap( -/*================*/ - page_t* page, /*!< in/out: index page */ - page_zip_des_t* page_zip,/*!< in/out: compressed page with enough - space available for inserting the record, - or NULL */ - ulint need, /*!< in: total number of bytes needed */ - ulint* heap_no)/*!< out: this contains the heap number - of the allocated record - if allocation succeeds */ -{ - byte* block; - ulint avl_space; - - ut_ad(page && heap_no); - - avl_space = page_get_max_insert_size(page, 1); - - if (avl_space >= need) { - block = page_header_get_ptr(page, PAGE_HEAP_TOP); - - page_header_set_ptr(page, page_zip, PAGE_HEAP_TOP, - block + need); - *heap_no = page_dir_get_n_heap(page); - - page_dir_set_n_heap(page, page_zip, 1 + *heap_no); - - return(block); - } - - return(NULL); -} - #ifndef UNIV_HOTBACKUP /**********************************************************//** Writes a log record of page creation. */ diff --git a/storage/xtradb/btr/btr0cur.cc b/storage/xtradb/btr/btr0cur.cc index 5235fe434a9..7d97881f552 100644 --- a/storage/xtradb/btr/btr0cur.cc +++ b/storage/xtradb/btr/btr0cur.cc @@ -3,7 +3,7 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2015, 2017, MariaDB Corporation. +Copyright (c) 2015, 2020, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1542,17 +1542,23 @@ fail_err: } ulint max_size = page_get_max_insert_size_after_reorganize(page, 1); + if (max_size < rec_size) { + goto fail; + } + + const ulint n_recs = page_get_n_recs(page); + if (UNIV_UNLIKELY(n_recs >= 8189)) { + ut_ad(srv_page_size == 65536); + goto fail; + } if (page_has_garbage(page)) { - if ((max_size < rec_size - || max_size < BTR_CUR_PAGE_REORGANIZE_LIMIT) - && page_get_n_recs(page) > 1 + if (max_size < BTR_CUR_PAGE_REORGANIZE_LIMIT + && n_recs > 1 && page_get_max_insert_size(page, 1) < rec_size) { goto fail; } - } else if (max_size < rec_size) { - goto fail; } /* If there have been many consecutive inserts to the diff --git a/storage/xtradb/include/page0page.h b/storage/xtradb/include/page0page.h index 2efc2d302a1..b377aa68ac7 100644 --- a/storage/xtradb/include/page0page.h +++ b/storage/xtradb/include/page0page.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2020, 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 @@ -749,21 +749,6 @@ page_mem_alloc_free( free record list */ ulint need); /*!< in: number of bytes allocated */ /************************************************************//** -Allocates a block of memory from the heap of an index page. -@return pointer to start of allocated buffer, or NULL if allocation fails */ -UNIV_INTERN -byte* -page_mem_alloc_heap( -/*================*/ - page_t* page, /*!< in/out: index page */ - page_zip_des_t* page_zip,/*!< in/out: compressed page with enough - space available for inserting the record, - or NULL */ - ulint need, /*!< in: total number of bytes needed */ - ulint* heap_no);/*!< out: this contains the heap number - of the allocated record - if allocation succeeds */ -/************************************************************//** Puts a record to free list. */ UNIV_INLINE void diff --git a/storage/xtradb/page/page0cur.cc b/storage/xtradb/page/page0cur.cc index e9ac4b4bb04..94e861ab554 100644 --- a/storage/xtradb/page/page0cur.cc +++ b/storage/xtradb/page/page0cur.cc @@ -2,6 +2,7 @@ Copyright (c) 1994, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2020, 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 @@ -941,6 +942,52 @@ page_cur_parse_insert_rec( return(ptr + end_seg_len); } +/************************************************************//** +Allocates a block of memory from the heap of an index page. +@return pointer to start of allocated buffer, or NULL if allocation fails */ +static +byte* +page_mem_alloc_heap( +/*================*/ + page_t* page, /*!< in/out: index page */ + page_zip_des_t* page_zip,/*!< in/out: compressed page with enough + space available for inserting the record, + or NULL */ + ulint need, /*!< in: total number of bytes needed */ + ulint* heap_no)/*!< out: this contains the heap number + of the allocated record + if allocation succeeds */ +{ + byte* block; + ulint avl_space; + + ut_ad(page && heap_no); + + avl_space = page_get_max_insert_size(page, 1); + + if (avl_space >= need) { + const ulint h = page_dir_get_n_heap(page); + if (UNIV_UNLIKELY(h >= 8191)) { + /* At the minimum record size of 5+2 bytes, + we can only reach this condition when using + innodb_page_size=64k. */ + ut_ad(srv_page_size == 65536); + return(NULL); + } + *heap_no = h; + + block = page_header_get_ptr(page, PAGE_HEAP_TOP); + + page_header_set_ptr(page, page_zip, PAGE_HEAP_TOP, + block + need); + page_dir_set_n_heap(page, page_zip, 1 + *heap_no); + + return(block); + } + + return(NULL); +} + /***********************************************************//** Inserts a record next to page cursor on an uncompressed page. Returns pointer to inserted record if succeed, i.e., enough diff --git a/storage/xtradb/page/page0page.cc b/storage/xtradb/page/page0page.cc index 16587f872ef..ee31c9dbd87 100644 --- a/storage/xtradb/page/page0page.cc +++ b/storage/xtradb/page/page0page.cc @@ -2,7 +2,7 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2018, MariaDB Corporation. +Copyright (c) 2018, 2020, 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 @@ -240,44 +240,6 @@ page_set_max_trx_id( } } -/************************************************************//** -Allocates a block of memory from the heap of an index page. -@return pointer to start of allocated buffer, or NULL if allocation fails */ -UNIV_INTERN -byte* -page_mem_alloc_heap( -/*================*/ - page_t* page, /*!< in/out: index page */ - page_zip_des_t* page_zip,/*!< in/out: compressed page with enough - space available for inserting the record, - or NULL */ - ulint need, /*!< in: total number of bytes needed */ - ulint* heap_no)/*!< out: this contains the heap number - of the allocated record - if allocation succeeds */ -{ - byte* block; - ulint avl_space; - - ut_ad(page && heap_no); - - avl_space = page_get_max_insert_size(page, 1); - - if (avl_space >= need) { - block = page_header_get_ptr(page, PAGE_HEAP_TOP); - - page_header_set_ptr(page, page_zip, PAGE_HEAP_TOP, - block + need); - *heap_no = page_dir_get_n_heap(page); - - page_dir_set_n_heap(page, page_zip, 1 + *heap_no); - - return(block); - } - - return(NULL); -} - #ifndef UNIV_HOTBACKUP /**********************************************************//** Writes a log record of page creation. */ From 101ce10d0ddda1e38806b8d2c491298482e7ab78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 12 Aug 2020 18:35:21 +0300 Subject: [PATCH 13/14] MDEV-20672 Inconsistent usage message for innodb_compression_algorithm The usage message for the innodb_compression_algorithm system variable did not list snappy, which was added as an optional compression algorithm in MariaDB 10.1.3 and might actually work since commit 90c52e5291b3ad0935df7da56ec0fcbf530733b4 (MDEV-12615) in MariaDB 10.1.24. Unfortunately, we will include also unavailable compression algorithms in the list, because ENUM parameters allow numeric values, and we do not want innodb_compression_algorithm=3 to change meaning depending on the way how the source code was compiled. --- mysql-test/suite/sys_vars/r/sysvars_innodb.result | 2 +- storage/innobase/handler/ha_innodb.cc | 2 +- storage/xtradb/handler/ha_innodb.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index d5d49a9b193..3877164bde3 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -502,7 +502,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE zlib VARIABLE_SCOPE GLOBAL VARIABLE_TYPE ENUM -VARIABLE_COMMENT Compression algorithm used on page compression. One of: none, zlib, lz4, lzo, lzma, or bzip2 +VARIABLE_COMMENT Compression algorithm used on page compression. One of: none, zlib, lz4, lzo, lzma, bzip2, or snappy NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 10098a2fa4d..8960f42b4a3 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -19862,7 +19862,7 @@ static TYPELIB page_compression_algorithms_typelib= }; static MYSQL_SYSVAR_ENUM(compression_algorithm, innodb_compression_algorithm, PLUGIN_VAR_OPCMDARG, - "Compression algorithm used on page compression. One of: none, zlib, lz4, lzo, lzma, or bzip2", + "Compression algorithm used on page compression. One of: none, zlib, lz4, lzo, lzma, bzip2, or snappy", innodb_compression_algorithm_validate, NULL, /* We use here the largest number of supported compression method to enable all those methods that are available. Availability of compression diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index bb324faf2b6..44c0c8d5bc5 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -21141,7 +21141,7 @@ static TYPELIB page_compression_algorithms_typelib= }; static MYSQL_SYSVAR_ENUM(compression_algorithm, innodb_compression_algorithm, PLUGIN_VAR_OPCMDARG, - "Compression algorithm used on page compression. One of: none, zlib, lz4, lzo, lzma, or bzip2", + "Compression algorithm used on page compression. One of: none, zlib, lz4, lzo, lzma, bzip2, or snappy", innodb_compression_algorithm_validate, NULL, /* We use here the largest number of supported compression method to enable all those methods that are available. Availability of compression From 7c2aad6be2bc94e022b39cdffe218604d91d410a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 13 Aug 2020 17:43:37 +0300 Subject: [PATCH 14/14] MDEV-23463 fil_page_decompress() debug check wastes 128KiB of stack fil_page_decompress(): Remove a rather useless debug check. We should have test coverage for reading page_compressed pages from files, either due to buffer pool page eviction or due to server restarts. A similar check was removed from fil_space_encrypt() in commit 0b36c27e0c06b798b7322ab07d8464b69a7b716c (MDEV-20307). --- storage/innobase/fil/fil0pagecompress.cc | 14 +------------- storage/xtradb/fil/fil0pagecompress.cc | 14 +------------- 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/storage/innobase/fil/fil0pagecompress.cc b/storage/innobase/fil/fil0pagecompress.cc index edc1fa913e7..656d1d46a6a 100644 --- a/storage/innobase/fil/fil0pagecompress.cc +++ b/storage/innobase/fil/fil0pagecompress.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (C) 2013, 2018, MariaDB Corporation. +Copyright (C) 2013, 2020, 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 @@ -243,24 +243,12 @@ success: /* Set up the actual payload lenght */ mach_write_to_2(out_buf+FIL_PAGE_DATA, write_size); -#ifdef UNIV_DEBUG - /* Verify */ ut_ad(fil_page_is_compressed(out_buf) || fil_page_is_compressed_encrypted(out_buf)); ut_ad(mach_read_from_4(out_buf+FIL_PAGE_SPACE_OR_CHKSUM) == BUF_NO_CHECKSUM_MAGIC); ut_ad(mach_read_from_2(out_buf+FIL_PAGE_DATA) == write_size); ut_ad(mach_read_from_8(out_buf+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION) == (ulint)comp_method || mach_read_from_2(out_buf+FIL_PAGE_DATA+FIL_PAGE_COMPRESSED_SIZE) == (ulint)comp_method); - /* Verify that page can be decompressed */ - { - page_t tmp_buf[UNIV_PAGE_SIZE_MAX]; - page_t page[UNIV_PAGE_SIZE_MAX]; - memcpy(page, out_buf, srv_page_size); - ut_ad(fil_page_decompress(tmp_buf, page)); - ut_ad(!buf_page_is_corrupted(false, page, 0, NULL)); - } -#endif /* UNIV_DEBUG */ - write_size+=header_len; if (block_size <= 0) { diff --git a/storage/xtradb/fil/fil0pagecompress.cc b/storage/xtradb/fil/fil0pagecompress.cc index edc1fa913e7..656d1d46a6a 100644 --- a/storage/xtradb/fil/fil0pagecompress.cc +++ b/storage/xtradb/fil/fil0pagecompress.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (C) 2013, 2018, MariaDB Corporation. +Copyright (C) 2013, 2020, 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 @@ -243,24 +243,12 @@ success: /* Set up the actual payload lenght */ mach_write_to_2(out_buf+FIL_PAGE_DATA, write_size); -#ifdef UNIV_DEBUG - /* Verify */ ut_ad(fil_page_is_compressed(out_buf) || fil_page_is_compressed_encrypted(out_buf)); ut_ad(mach_read_from_4(out_buf+FIL_PAGE_SPACE_OR_CHKSUM) == BUF_NO_CHECKSUM_MAGIC); ut_ad(mach_read_from_2(out_buf+FIL_PAGE_DATA) == write_size); ut_ad(mach_read_from_8(out_buf+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION) == (ulint)comp_method || mach_read_from_2(out_buf+FIL_PAGE_DATA+FIL_PAGE_COMPRESSED_SIZE) == (ulint)comp_method); - /* Verify that page can be decompressed */ - { - page_t tmp_buf[UNIV_PAGE_SIZE_MAX]; - page_t page[UNIV_PAGE_SIZE_MAX]; - memcpy(page, out_buf, srv_page_size); - ut_ad(fil_page_decompress(tmp_buf, page)); - ut_ad(!buf_page_is_corrupted(false, page, 0, NULL)); - } -#endif /* UNIV_DEBUG */ - write_size+=header_len; if (block_size <= 0) {