diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-11-12 15:54:08 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-11-12 15:54:08 +0200 |
commit | 254bb1c35bbb10a043482e8f1f7c139a32b836f6 (patch) | |
tree | 0d5dcbc797c8400bd041945472ec5a351ae60c51 | |
parent | ef639f1a93b87abd759c8fe815d490954fe3e594 (diff) | |
parent | 97569d3c37a66bc941b933ac7c2cefa5430a5175 (diff) | |
download | mariadb-git-254bb1c35bbb10a043482e8f1f7c139a32b836f6.tar.gz |
Merge 10.5 into 10.6
-rw-r--r-- | include/my_atomic_wrapper.h | 1 | ||||
-rw-r--r-- | mysql-test/include/innodb_checksum_algorithm.combinations | 2 | ||||
-rw-r--r-- | mysql-test/main/range.result | 35 | ||||
-rw-r--r-- | mysql-test/main/range.test | 46 | ||||
-rw-r--r-- | mysql-test/main/range_mrr_icp.result | 35 | ||||
-rw-r--r-- | mysql-test/suite/maria/create.test | 5 | ||||
-rw-r--r-- | mysql-test/suite/sys_vars/r/innodb_flush_sync_basic.result | 10 | ||||
-rw-r--r-- | mysql-test/suite/sys_vars/t/innodb_flush_sync_basic.test | 7 | ||||
-rw-r--r-- | sql/opt_range.cc | 14 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 21 | ||||
-rw-r--r-- | storage/innobase/buf/buf0flu.cc | 112 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 25 | ||||
-rw-r--r-- | storage/innobase/handler/i_s.cc | 13 | ||||
-rw-r--r-- | storage/innobase/include/ha_prototypes.h | 4 | ||||
-rw-r--r-- | storage/innobase/include/log0log.h | 6 | ||||
-rw-r--r-- | storage/innobase/lock/lock0lock.cc | 2 | ||||
-rw-r--r-- | storage/innobase/log/log0log.cc | 4 | ||||
-rw-r--r-- | storage/innobase/log/log0recv.cc | 37 | ||||
-rw-r--r-- | storage/innobase/trx/trx0rec.cc | 41 | ||||
-rw-r--r-- | tests/mysql_client_test.c | 7 |
20 files changed, 278 insertions, 149 deletions
diff --git a/include/my_atomic_wrapper.h b/include/my_atomic_wrapper.h index 64835e30ca7..c0e18ea7c91 100644 --- a/include/my_atomic_wrapper.h +++ b/include/my_atomic_wrapper.h @@ -13,6 +13,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ +#pragma once #ifdef __cplusplus #include <atomic> /** diff --git a/mysql-test/include/innodb_checksum_algorithm.combinations b/mysql-test/include/innodb_checksum_algorithm.combinations index fd237e1190a..039bfaef676 100644 --- a/mysql-test/include/innodb_checksum_algorithm.combinations +++ b/mysql-test/include/innodb_checksum_algorithm.combinations @@ -3,9 +3,11 @@ [strict_crc32] --innodb-checksum-algorithm=strict_crc32 +--innodb-flush-sync=OFF [full_crc32] --innodb-checksum-algorithm=full_crc32 [strict_full_crc32] --innodb-checksum-algorithm=strict_full_crc32 +--innodb-flush-sync=OFF diff --git a/mysql-test/main/range.result b/mysql-test/main/range.result index a9c3b9c6e2a..7fa6058b892 100644 --- a/mysql-test/main/range.result +++ b/mysql-test/main/range.result @@ -1297,7 +1297,7 @@ SELECT * FROM t1 WHERE 25 <= a AND b = 23 OR 23 <= a; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range a a 5 NULL 2 Using where; Using index +1 SIMPLE t1 range a a 5 NULL 3 Using where; Using index SELECT * FROM t1 WHERE 23 <= a AND a <= 25 OR 25 <= a AND b = 23 OR @@ -3121,6 +3121,39 @@ a b set eq_range_index_dive_limit=default; drop table t1; # +# MDEV-24117: Memory management problem in statistics state... +# (just the testcase) +# +create table t0(a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1(a int); +insert into t1 +select A.a + B.a* 10 + C.a * 100 + D.a * 1000 +from t0 A, t0 B, t0 C, t0 D +where D.a<4; +create table t2 ( +a int, +b int, +key(a) +); +insert into t2 values (1,1),(2,2),(3,3); +set @query=(select group_concat(a) from t1); +set @tmp_24117= @@max_session_mem_used; +# +# On debug build, the usage was +# - 2.8M without the bug +# - 1G with the bug. +set max_session_mem_used=64*1024*1024; +set @query=concat('explain select * from t2 where a=1 or a in (', @query, ')'); +prepare s from @query; +# This should not fail with an error: +execute s; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL a NULL NULL NULL 3 Using where +set max_session_mem_used=@tmp_24117; +deallocate prepare s; +drop table t0,t1,t2; +# # MDEV-23811: Both disjunct of WHERE condition contain range conditions # for the same index such that the second range condition # fully covers the first one. Additionally one of the disjuncts diff --git a/mysql-test/main/range.test b/mysql-test/main/range.test index 8b25c0dffcc..b3a0bfe7ebc 100644 --- a/mysql-test/main/range.test +++ b/mysql-test/main/range.test @@ -2093,6 +2093,52 @@ set eq_range_index_dive_limit=default; drop table t1; --echo # +--echo # MDEV-24117: Memory management problem in statistics state... +--echo # (just the testcase) +--echo # + +create table t0(a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); + +create table t1(a int); + +# 4K rows +insert into t1 +select A.a + B.a* 10 + C.a * 100 + D.a * 1000 +from t0 A, t0 B, t0 C, t0 D +where D.a<4; + +create table t2 ( + a int, + b int, + key(a) +); + +insert into t2 values (1,1),(2,2),(3,3); + +set @query=(select group_concat(a) from t1); + +set @tmp_24117= @@max_session_mem_used; + +--echo # +--echo # On debug build, the usage was +--echo # - 2.8M without the bug +--echo # - 1G with the bug. + +set max_session_mem_used=64*1024*1024; + +set @query=concat('explain select * from t2 where a=1 or a in (', @query, ')'); + +prepare s from @query; + +--echo # This should not fail with an error: +execute s; +set max_session_mem_used=@tmp_24117; + +deallocate prepare s; + +drop table t0,t1,t2; +--echo # --echo # MDEV-23811: Both disjunct of WHERE condition contain range conditions --echo # for the same index such that the second range condition --echo # fully covers the first one. Additionally one of the disjuncts diff --git a/mysql-test/main/range_mrr_icp.result b/mysql-test/main/range_mrr_icp.result index 37a6f2de2fd..e94c2598aad 100644 --- a/mysql-test/main/range_mrr_icp.result +++ b/mysql-test/main/range_mrr_icp.result @@ -1300,7 +1300,7 @@ SELECT * FROM t1 WHERE 25 <= a AND b = 23 OR 23 <= a; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range a a 5 NULL 2 Using where; Using index +1 SIMPLE t1 range a a 5 NULL 3 Using where; Using index SELECT * FROM t1 WHERE 23 <= a AND a <= 25 OR 25 <= a AND b = 23 OR @@ -3110,6 +3110,39 @@ a b set eq_range_index_dive_limit=default; drop table t1; # +# MDEV-24117: Memory management problem in statistics state... +# (just the testcase) +# +create table t0(a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1(a int); +insert into t1 +select A.a + B.a* 10 + C.a * 100 + D.a * 1000 +from t0 A, t0 B, t0 C, t0 D +where D.a<4; +create table t2 ( +a int, +b int, +key(a) +); +insert into t2 values (1,1),(2,2),(3,3); +set @query=(select group_concat(a) from t1); +set @tmp_24117= @@max_session_mem_used; +# +# On debug build, the usage was +# - 2.8M without the bug +# - 1G with the bug. +set max_session_mem_used=64*1024*1024; +set @query=concat('explain select * from t2 where a=1 or a in (', @query, ')'); +prepare s from @query; +# This should not fail with an error: +execute s; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL a NULL NULL NULL 3 Using where +set max_session_mem_used=@tmp_24117; +deallocate prepare s; +drop table t0,t1,t2; +# # MDEV-23811: Both disjunct of WHERE condition contain range conditions # for the same index such that the second range condition # fully covers the first one. Additionally one of the disjuncts diff --git a/mysql-test/suite/maria/create.test b/mysql-test/suite/maria/create.test index 3e0be3ebb9b..3937d800fed 100644 --- a/mysql-test/suite/maria/create.test +++ b/mysql-test/suite/maria/create.test @@ -86,11 +86,6 @@ flush tables; --error 1,ER_TABLE_EXISTS_ERROR --eval CREATE TABLE MDEV_23222 (i INT) DATA DIRECTORY = '$MYSQL_TMP_DIR', ENGINE=Aria TRANSACTIONAL=1; DROP TABLE t1; ---disable_warnings ---remove_file $mysqld_datadir/test/MDEV_23222.MAD ---replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR ---remove_file $MYSQL_TMP_DIR/MDEV_23222.MAD ---enable_warnings --echo # --echo # End of 10.3 tests diff --git a/mysql-test/suite/sys_vars/r/innodb_flush_sync_basic.result b/mysql-test/suite/sys_vars/r/innodb_flush_sync_basic.result index 9e3f7d95eb9..f45954ae1f8 100644 --- a/mysql-test/suite/sys_vars/r/innodb_flush_sync_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_flush_sync_basic.result @@ -1,16 +1,11 @@ SET @start_global_value = @@global.innodb_flush_sync; -SELECT @start_global_value; -@start_global_value -1 Valid values are 'ON' and 'OFF' select @@global.innodb_flush_sync in (0, 1); @@global.innodb_flush_sync in (0, 1) 1 -select @@global.innodb_flush_sync; -@@global.innodb_flush_sync -1 select @@session.innodb_flush_sync; ERROR HY000: Variable 'innodb_flush_sync' is a GLOBAL variable +SET GLOBAL innodb_flush_sync = ON; show global variables like 'innodb_flush_sync'; Variable_name Value innodb_flush_sync ON @@ -87,6 +82,3 @@ INNODB_FLUSH_SYNC ON set global innodb_flush_sync='AUTO'; ERROR 42000: Variable 'innodb_flush_sync' can't be set to the value of 'AUTO' SET @@global.innodb_flush_sync = @start_global_value; -SELECT @@global.innodb_flush_sync; -@@global.innodb_flush_sync -1 diff --git a/mysql-test/suite/sys_vars/t/innodb_flush_sync_basic.test b/mysql-test/suite/sys_vars/t/innodb_flush_sync_basic.test index a73575864bd..cb91cf87d83 100644 --- a/mysql-test/suite/sys_vars/t/innodb_flush_sync_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_flush_sync_basic.test @@ -1,16 +1,15 @@ --source include/have_innodb.inc SET @start_global_value = @@global.innodb_flush_sync; -SELECT @start_global_value; # # exists as global only # --echo Valid values are 'ON' and 'OFF' select @@global.innodb_flush_sync in (0, 1); -select @@global.innodb_flush_sync; --error ER_INCORRECT_GLOBAL_LOCAL_VAR select @@session.innodb_flush_sync; +SET GLOBAL innodb_flush_sync = ON; show global variables like 'innodb_flush_sync'; show session variables like 'innodb_flush_sync'; --disable_warnings @@ -18,9 +17,6 @@ select * from information_schema.global_variables where variable_name='innodb_fl select * from information_schema.session_variables where variable_name='innodb_flush_sync'; --enable_warnings -# -# show that it's writable -# set global innodb_flush_sync='OFF'; select @@global.innodb_flush_sync; --disable_warnings @@ -74,4 +70,3 @@ set global innodb_flush_sync='AUTO'; # SET @@global.innodb_flush_sync = @start_global_value; -SELECT @@global.innodb_flush_sync; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index adc0572cb1c..cb5a0604733 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -9619,15 +9619,9 @@ tree_or(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2) } bool no_imerge_from_ranges= FALSE; - SEL_TREE *rt1= tree1; - SEL_TREE *rt2= tree2; /* Build the range part of the tree for the formula (1) */ if (sel_trees_can_be_ored(param, tree1, tree2, &ored_keys)) { - if (no_merges1) - rt1= new SEL_TREE(tree1, TRUE, param); - if (no_merges2) - rt2= new SEL_TREE(tree2, TRUE, param); bool must_be_ored= sel_trees_must_be_ored(param, tree1, tree2, ored_keys); no_imerge_from_ranges= must_be_ored; @@ -9685,6 +9679,12 @@ tree_or(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2) else if (!no_ranges1 && !no_ranges2 && !no_imerge_from_ranges) { /* Build the imerge part of the tree for the formula (1) */ + SEL_TREE *rt1= tree1; + SEL_TREE *rt2= tree2; + if (no_merges1) + rt1= new SEL_TREE(tree1, TRUE, param); + if (no_merges2) + rt2= new SEL_TREE(tree2, TRUE, param); if (!rt1 || !rt2 || result->merges.push_back(imerge_from_ranges) || imerge_from_ranges->or_sel_tree(param, rt1) || @@ -10350,7 +10350,7 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2) if (!tmp->next_key_part) { SEL_ARG *key2_next= key2->next; - if (key2->use_count) + if (key2_shared) { SEL_ARG *key2_cpy= new SEL_ARG(*key2); if (!key2_cpy) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index ec76d1f3ff0..772d8f0b5e1 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -3252,10 +3252,19 @@ void mysqld_stmt_execute(THD *thd, char *packet_arg, uint packet_length) void mysqld_stmt_bulk_execute(THD *thd, char *packet_arg, uint packet_length) { uchar *packet= (uchar*)packet_arg; // GCC 4.0.1 workaround + DBUG_ENTER("mysqld_stmt_execute_bulk"); + + const uint packet_header_lenght= 4 + 2; //ID & 2 bytes of flags + + if (packet_length < packet_header_lenght) + { + my_error(ER_MALFORMED_PACKET, MYF(0)); + DBUG_VOID_RETURN; + } + ulong stmt_id= uint4korr(packet); uint flags= (uint) uint2korr(packet + 4); uchar *packet_end= packet + packet_length; - DBUG_ENTER("mysqld_stmt_execute_bulk"); if (!(thd->client_capabilities & MARIADB_CLIENT_STMT_BULK_OPERATIONS)) @@ -3263,16 +3272,18 @@ void mysqld_stmt_bulk_execute(THD *thd, char *packet_arg, uint packet_length) DBUG_PRINT("error", ("An attempt to execute bulk operation without support")); my_error(ER_UNSUPPORTED_PS, MYF(0)); + DBUG_VOID_RETURN; } /* Check for implemented parameters */ if (flags & (~STMT_BULK_FLAG_CLIENT_SEND_TYPES)) { DBUG_PRINT("error", ("unsupported bulk execute flags %x", flags)); my_error(ER_UNSUPPORTED_PS, MYF(0)); + DBUG_VOID_RETURN; } /* stmt id and two bytes of flags */ - packet+= 4 + 2; + packet+= packet_header_lenght; mysql_stmt_execute_common(thd, stmt_id, packet, packet_end, 0, TRUE, (flags & STMT_BULK_FLAG_CLIENT_SEND_TYPES)); DBUG_VOID_RETURN; @@ -3349,9 +3360,11 @@ stmt_execute_packet_sanity_check(Prepared_statement *stmt, { /* If there is no parameters, this should be normally already end - of the packet. If it's not - then error + of the packet, but it is not a problem if something left (popular + mistake in protocol implementation) because we will not read anymore + from the buffer. */ - return (packet_end > packet); + return false; } return false; } diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index ac6c45deeab..316c1822f0b 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -1681,52 +1681,55 @@ ATTRIBUTE_COLD void buf_flush_wait_flushed(lsn_t sync_lsn) mysql_mutex_lock(&buf_pool.flush_list_mutex); -#if 1 /* FIXME: remove this, and guarantee that the page cleaner serves us */ - if (UNIV_UNLIKELY(!buf_page_cleaner_is_active) - ut_d(|| innodb_page_cleaner_disabled_debug)) + if (buf_pool.get_oldest_modification(sync_lsn) < sync_lsn) { - for (;;) +#if 1 /* FIXME: remove this, and guarantee that the page cleaner serves us */ + if (UNIV_UNLIKELY(!buf_page_cleaner_is_active) + ut_d(|| innodb_page_cleaner_disabled_debug)) { - const lsn_t lsn= buf_pool.get_oldest_modification(sync_lsn); - mysql_mutex_unlock(&buf_pool.flush_list_mutex); - if (lsn >= sync_lsn) - return; - ulint n_pages= buf_flush_lists(srv_max_io_capacity, sync_lsn); - buf_flush_wait_batch_end_acquiring_mutex(false); - if (n_pages) + do { - MONITOR_INC_VALUE_CUMULATIVE(MONITOR_FLUSH_SYNC_TOTAL_PAGE, - MONITOR_FLUSH_SYNC_COUNT, - MONITOR_FLUSH_SYNC_PAGES, n_pages); - log_checkpoint(); + mysql_mutex_unlock(&buf_pool.flush_list_mutex); + ulint n_pages= buf_flush_lists(srv_max_io_capacity, sync_lsn); + buf_flush_wait_batch_end_acquiring_mutex(false); + if (n_pages) + { + MONITOR_INC_VALUE_CUMULATIVE(MONITOR_FLUSH_SYNC_TOTAL_PAGE, + MONITOR_FLUSH_SYNC_COUNT, + MONITOR_FLUSH_SYNC_PAGES, n_pages); + } + MONITOR_INC(MONITOR_FLUSH_SYNC_WAITS); + mysql_mutex_lock(&buf_pool.flush_list_mutex); } - MONITOR_INC(MONITOR_FLUSH_SYNC_WAITS); - mysql_mutex_lock(&buf_pool.flush_list_mutex); + while (buf_pool.get_oldest_modification(sync_lsn) < sync_lsn); + + goto try_checkpoint; } - return; - } - else if (UNIV_LIKELY(srv_flush_sync)) #endif - { if (buf_flush_sync_lsn < sync_lsn) { buf_flush_sync_lsn= sync_lsn; mysql_cond_signal(&buf_pool.do_flush_list); } - } - while (buf_pool.get_oldest_modification(sync_lsn) < sync_lsn) - { - tpool::tpool_wait_begin(); - thd_wait_begin(nullptr, THD_WAIT_DISKIO); - mysql_cond_wait(&buf_pool.done_flush_list, &buf_pool.flush_list_mutex); - thd_wait_end(nullptr); - tpool::tpool_wait_end(); + do + { + tpool::tpool_wait_begin(); + thd_wait_begin(nullptr, THD_WAIT_DISKIO); + mysql_cond_wait(&buf_pool.done_flush_list, &buf_pool.flush_list_mutex); + thd_wait_end(nullptr); + tpool::tpool_wait_end(); - MONITOR_INC(MONITOR_FLUSH_SYNC_WAITS); + MONITOR_INC(MONITOR_FLUSH_SYNC_WAITS); + } + while (buf_pool.get_oldest_modification(sync_lsn) < sync_lsn); } +try_checkpoint: mysql_mutex_unlock(&buf_pool.flush_list_mutex); + + if (UNIV_UNLIKELY(log_sys.last_checkpoint_lsn < sync_lsn)) + log_checkpoint(); } /** If innodb_flush_sync=ON, initiate a furious flush. @@ -1739,8 +1742,7 @@ void buf_flush_ahead(lsn_t lsn) if (recv_recovery_is_on()) recv_sys.apply(true); - if (buf_flush_sync_lsn < lsn && - UNIV_LIKELY(srv_flush_sync) && UNIV_LIKELY(buf_page_cleaner_is_active)) + if (buf_flush_sync_lsn < lsn) { mysql_mutex_lock(&buf_pool.flush_list_mutex); if (buf_flush_sync_lsn < lsn) @@ -2054,13 +2056,15 @@ static os_thread_ret_t DECLARE_THREAD(buf_flush_page_cleaner)(void*) if (UNIV_UNLIKELY(lsn_limit != 0)) { furious_flush: - buf_flush_sync_for_checkpoint(lsn_limit); - last_pages= 0; - set_timespec(abstime, 1); - continue; + if (UNIV_LIKELY(srv_flush_sync)) + { + buf_flush_sync_for_checkpoint(lsn_limit); + last_pages= 0; + set_timespec(abstime, 1); + continue; + } } - - if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) + else if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) break; mysql_cond_timedwait(&buf_pool.do_flush_list, &buf_pool.flush_list_mutex, @@ -2070,15 +2074,25 @@ furious_flush: lsn_limit= buf_flush_sync_lsn; if (UNIV_UNLIKELY(lsn_limit != 0)) - goto furious_flush; - - if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) + { + if (UNIV_LIKELY(srv_flush_sync)) + goto furious_flush; + } + else if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) break; const ulint dirty_blocks= UT_LIST_GET_LEN(buf_pool.flush_list); if (!dirty_blocks) + { + if (UNIV_UNLIKELY(lsn_limit != 0)) + { + buf_flush_sync_lsn= 0; + /* wake up buf_flush_wait_flushed() */ + mysql_cond_broadcast(&buf_pool.done_flush_list); + } continue; + } /* We perform dirty reads of the LRU+free list lengths here. Division by zero is not possible, because buf_pool.flush_list is @@ -2086,19 +2100,29 @@ furious_flush: const double dirty_pct= double(dirty_blocks) * 100.0 / double(UT_LIST_GET_LEN(buf_pool.LRU) + UT_LIST_GET_LEN(buf_pool.free)); - if (dirty_pct < srv_max_dirty_pages_pct_lwm) + if (dirty_pct < srv_max_dirty_pages_pct_lwm && !lsn_limit) continue; const lsn_t oldest_lsn= buf_pool.get_oldest_modification(0); + if (UNIV_UNLIKELY(lsn_limit != 0) && oldest_lsn >= lsn_limit) + buf_flush_sync_lsn= 0; + mysql_mutex_unlock(&buf_pool.flush_list_mutex); ulint n_flushed; - if (!srv_adaptive_flushing) + if (UNIV_UNLIKELY(lsn_limit != 0)) + { + n_flushed= buf_flush_lists(srv_max_io_capacity, lsn_limit); + /* wake up buf_flush_wait_flushed() */ + mysql_cond_broadcast(&buf_pool.done_flush_list); + goto try_checkpoint; + } + else if (!srv_adaptive_flushing) { n_flushed= buf_flush_lists(srv_io_capacity, LSN_MAX); - +try_checkpoint: if (n_flushed) { MONITOR_INC_VALUE_CUMULATIVE(MONITOR_FLUSH_BACKGROUND_TOTAL_PAGE, diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 32437810adb..0da00cabeb1 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -18322,24 +18322,6 @@ static struct st_mysql_storage_engine innobase_storage_engine= { MYSQL_HANDLERTON_INTERFACE_VERSION }; #ifdef WITH_WSREP -void -wsrep_abort_slave_trx( -/*==================*/ - wsrep_seqno_t bf_seqno, - wsrep_seqno_t victim_seqno) -{ - WSREP_ERROR("Trx %lld tries to abort slave trx %lld. This could be " - "caused by:\n\t" - "1) unsupported configuration options combination, please check documentation.\n\t" - "2) a bug in the code.\n\t" - "3) a database corruption.\n Node consistency compromized, " - "need to abort. Restart the node to resync with cluster.", - (long long)bf_seqno, (long long)victim_seqno); - abort(); -} - -/*******************************************************************//** -This function is used to kill one transaction in BF. */ /** This function is used to kill one transaction. @@ -18364,10 +18346,7 @@ comparison as in the local certification failure. @param[in] bf_thd Brute force (BF) thread @param[in,out] victim_trx Vimtim trx to be killed @param[in] signal Should victim be signaled */ -UNIV_INTERN -int -wsrep_innobase_kill_one_trx(THD* bf_thd, trx_t *victim_trx, - bool signal) +int wsrep_innobase_kill_one_trx(THD *bf_thd, trx_t *victim_trx, bool signal) { ut_ad(bf_thd); ut_ad(victim_trx); @@ -18376,7 +18355,7 @@ wsrep_innobase_kill_one_trx(THD* bf_thd, trx_t *victim_trx, DBUG_ENTER("wsrep_innobase_kill_one_trx"); - THD *thd= (THD *) victim_trx->mysql_thd; + THD *thd= victim_trx->mysql_thd; ut_ad(thd); /* Note that bf_trx might not exist here e.g. on MDL conflict case (test: galera_concurrent_ctas). Similarly, BF thread diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index af51dd7c043..bfea5613b19 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -6786,6 +6786,7 @@ i_s_tablespaces_encryption_fill_table( DBUG_RETURN(0); } + int err = 0; mutex_enter(&fil_system.mutex); fil_system.freeze_space_list++; @@ -6795,19 +6796,19 @@ i_s_tablespaces_encryption_fill_table( && !space->is_stopping()) { space->reacquire(); mutex_exit(&fil_system.mutex); - if (int err = i_s_dict_fill_tablespaces_encryption( - thd, space, tables->table)) { - space->release(); - DBUG_RETURN(err); - } + err = i_s_dict_fill_tablespaces_encryption( + thd, space, tables->table); mutex_enter(&fil_system.mutex); space->release(); + if (err) { + break; + } } } fil_system.freeze_space_list--; mutex_exit(&fil_system.mutex); - DBUG_RETURN(0); + DBUG_RETURN(err); } /*******************************************************************//** Bind the dynamic table INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index 965bff78795..1acf951baec 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -217,9 +217,7 @@ innobase_casedn_str( char* a); /*!< in/out: string to put in lower case */ #ifdef WITH_WSREP -int -wsrep_innobase_kill_one_trx(THD *bf_thd, trx_t *victim_trx, - bool signal); +int wsrep_innobase_kill_one_trx(THD *bf_thd, trx_t *victim_trx, bool signal); ulint wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, unsigned char* str, ulint str_length, unsigned int buf_length); diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index 5a26b4baf7d..1a79738bc9b 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -37,7 +37,7 @@ Created 12/9/1995 Heikki Tuuri #include "log0types.h" #include "os0file.h" #include "span.h" -#include <atomic> +#include "my_atomic_wrapper.h" #include <vector> #include <string> @@ -615,8 +615,8 @@ public: new query step is started */ ib_uint64_t next_checkpoint_no; /*!< next checkpoint number */ - lsn_t last_checkpoint_lsn; - /*!< latest checkpoint lsn */ + /** latest completed checkpoint (protected by log_sys.mutex) */ + Atomic_relaxed<lsn_t> last_checkpoint_lsn; lsn_t next_checkpoint_lsn; /*!< next checkpoint lsn */ ulint n_pending_checkpoint_writes; diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 24a2249f3f6..f2f4b732f15 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -4753,7 +4753,7 @@ lock_validate() lock_mutex_exit(); - for (const page_id_t page_id : pages) { + for (page_id_t page_id : pages) { lock_rec_block_validate(page_id); } diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index ba4c8bb8d62..4a063765569 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -918,7 +918,7 @@ ATTRIBUTE_COLD void log_write_checkpoint_info(lsn_t end_lsn) DBUG_PRINT("ib_log", ("checkpoint ended at " LSN_PF ", flushed to " LSN_PF, - log_sys.last_checkpoint_lsn, + lsn_t{log_sys.last_checkpoint_lsn}, log_sys.get_flushed_lsn())); MONITOR_INC(MONITOR_NUM_CHECKPOINT); @@ -1233,7 +1233,7 @@ log_print( lsn, log_sys.get_flushed_lsn(), pages_flushed, - log_sys.last_checkpoint_lsn); + lsn_t{log_sys.last_checkpoint_lsn}); current_time = time(NULL); diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index c5cf21bf59a..fe691a4b256 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -96,13 +96,22 @@ struct log_phys_t : public log_rec_t /** start LSN of the mini-transaction (not necessarily of this record) */ const lsn_t start_lsn; private: - /** length of the record, in bytes */ - uint16_t len; + /** @return the start of length and data */ + const byte *start() const + { + return my_assume_aligned<sizeof(size_t)> + (reinterpret_cast<const byte*>(&start_lsn + 1)); + } + /** @return the start of length and data */ + byte *start() + { return const_cast<byte*>(const_cast<const log_phys_t*>(this)->start()); } + /** @return the length of the following record */ + uint16_t len() const { uint16_t i; memcpy(&i, start(), 2); return i; } /** @return start of the log records */ - byte *begin() { return reinterpret_cast<byte*>(&len + 1); } + byte *begin() { return start() + 2; } /** @return end of the log records */ - byte *end() { byte *e= begin() + len; ut_ad(!*e); return e; } + byte *end() { byte *e= begin() + len(); ut_ad(!*e); return e; } public: /** @return start of the log records */ const byte *begin() const { return const_cast<log_phys_t*>(this)->begin(); } @@ -112,11 +121,7 @@ public: /** Determine the allocated size of the object. @param len length of recs, excluding terminating NUL byte @return the total allocation size */ - static size_t alloc_size(size_t len) - { - return len + 1 + - reinterpret_cast<size_t>(reinterpret_cast<log_phys_t*>(0)->begin()); - } + static inline size_t alloc_size(size_t len); /** Constructor. @param start_lsn start LSN of the mini-transaction @@ -124,11 +129,13 @@ public: @param recs the first log record for the page in the mini-transaction @param size length of recs, in bytes, excluding terminating NUL byte */ log_phys_t(lsn_t start_lsn, lsn_t lsn, const byte *recs, size_t size) : - log_rec_t(lsn), start_lsn(start_lsn), len(static_cast<uint16_t>(size)) + log_rec_t(lsn), start_lsn(start_lsn) { ut_ad(start_lsn); ut_ad(start_lsn < lsn); + const uint16_t len= static_cast<uint16_t>(size); ut_ad(len == size); + memcpy(start(), &len, 2); reinterpret_cast<byte*>(memcpy(begin(), recs, size))[size]= 0; } @@ -138,8 +145,10 @@ public: void append(const byte *recs, size_t size) { ut_ad(start_lsn < lsn); + uint16_t l= len(); reinterpret_cast<byte*>(memcpy(end(), recs, size))[size]= 0; - len= static_cast<uint16_t>(len + size); + l= static_cast<uint16_t>(l + size); + memcpy(start(), &l, 2); } /** Apply an UNDO_APPEND record. @@ -514,6 +523,12 @@ page_corrupted: }; +inline size_t log_phys_t::alloc_size(size_t len) +{ + return len + (1 + 2 + sizeof(log_phys_t)); +} + + /** Tablespace item during recovery */ struct file_name_t { /** Tablespace file name (FILE_MODIFY) */ diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 52130b50eb1..1b1cabb6963 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -53,15 +53,18 @@ const dtuple_t trx_undo_metadata = { /*=========== UNDO LOG RECORD CREATION AND DECODING ====================*/ /** Calculate the free space left for extending an undo log record. -@param[in] undo_block undo log page -@param[in] ptr current end of the undo page +@param undo_block undo log page +@param ptr current end of the undo page @return bytes left */ -static ulint trx_undo_left(const buf_block_t* undo_block, const byte* ptr) +static ulint trx_undo_left(const buf_block_t *undo_block, const byte *ptr) { - /* The 10 is a safety margin, in case we have some small - calculation error below */ - return srv_page_size - ulint(ptr - undo_block->frame) - - (10 + FIL_PAGE_DATA_END); + ut_ad(ptr >= &undo_block->frame[TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE]); + ut_ad(ptr <= &undo_block->frame[srv_page_size - 10 - FIL_PAGE_DATA_END]); + + /* The 10 is supposed to be an extra safety margin (and needed for + compatibility with older versions) */ + return srv_page_size - ulint(ptr - undo_block->frame) - + (10 + FIL_PAGE_DATA_END); } /**********************************************************************//** @@ -133,17 +136,15 @@ trx_undo_log_v_idx( ut_ad(!vcol->v_indexes.empty()); - /* Size to reserve, max 5 bytes for each index id and position, plus - 5 bytes for num of indexes, 2 bytes for write total length. - 1 byte for undo log record format version marker */ - ulint size = 5 + 2 + (first_v_col ? 1 : 0); + ulint size = first_v_col ? 1 + 2 : 2; const ulint avail = trx_undo_left(undo_block, ptr); - if (avail < size) { + /* The mach_write_compressed(ptr, flen) in + trx_undo_page_report_modify() will consume additional 1 to 5 bytes. */ + if (avail < size + 5) { return(NULL); } - size = 0; ulint n_idx = 0; for (const auto& v_index : vcol->v_indexes) { n_idx++; @@ -151,12 +152,14 @@ trx_undo_log_v_idx( size += mach_get_compressed_size(uint32_t(v_index.index->id)); size += mach_get_compressed_size(v_index.nth_field); } - size += 2 + mach_get_compressed_size(n_idx); - if (avail < size) { + size += mach_get_compressed_size(n_idx); + + if (avail < size + 5) { return(NULL); } + ut_d(const byte* orig_ptr = ptr); if (first_v_col) { /* write the version marker */ @@ -179,6 +182,8 @@ trx_undo_log_v_idx( ptr += mach_write_compressed(ptr, v_index.nth_field); } + ut_ad(orig_ptr + size == ptr); + mach_write_to_2(old_ptr, ulint(ptr - old_ptr)); return(ptr); @@ -394,9 +399,6 @@ trx_undo_page_report_insert( + undo_block->frame)); byte* ptr = undo_block->frame + first_free; - ut_ad(first_free >= TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE); - ut_ad(first_free <= srv_page_size - FIL_PAGE_DATA_END); - if (trx_undo_left(undo_block, ptr) < 2 + 1 + 11 + 11) { /* Not enough space for writing the general parameters */ return(0); @@ -803,9 +805,6 @@ trx_undo_page_report_modify( const uint16_t first_free = mach_read_from_2(ptr_to_first_free); byte *ptr = undo_block->frame + first_free; - ut_ad(first_free >= TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE); - ut_ad(first_free <= srv_page_size - FIL_PAGE_DATA_END); - if (trx_undo_left(undo_block, ptr) < 50) { /* NOTE: the value 50 must be big enough so that the general fields written below fit on the undo log page */ diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 7d56a3a7e33..e043eeebdec 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -21076,8 +21076,11 @@ static void test_mdev19838() " VALUES " "(0x1111111111111111)", -1); - /* Expecting an error if parameters are sent */ - DIE_UNLESS(rc != 0 || paramCount == 0); + /* + We allow junk at the end of the packet in case of + no parameters. So it will succeed. + */ + DIE_UNLESS(rc == 0); } mysql_stmt_close(stmt); |