summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-11-12 15:54:08 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2020-11-12 15:54:08 +0200
commit254bb1c35bbb10a043482e8f1f7c139a32b836f6 (patch)
tree0d5dcbc797c8400bd041945472ec5a351ae60c51
parentef639f1a93b87abd759c8fe815d490954fe3e594 (diff)
parent97569d3c37a66bc941b933ac7c2cefa5430a5175 (diff)
downloadmariadb-git-254bb1c35bbb10a043482e8f1f7c139a32b836f6.tar.gz
Merge 10.5 into 10.6
-rw-r--r--include/my_atomic_wrapper.h1
-rw-r--r--mysql-test/include/innodb_checksum_algorithm.combinations2
-rw-r--r--mysql-test/main/range.result35
-rw-r--r--mysql-test/main/range.test46
-rw-r--r--mysql-test/main/range_mrr_icp.result35
-rw-r--r--mysql-test/suite/maria/create.test5
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_flush_sync_basic.result10
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_flush_sync_basic.test7
-rw-r--r--sql/opt_range.cc14
-rw-r--r--sql/sql_prepare.cc21
-rw-r--r--storage/innobase/buf/buf0flu.cc112
-rw-r--r--storage/innobase/handler/ha_innodb.cc25
-rw-r--r--storage/innobase/handler/i_s.cc13
-rw-r--r--storage/innobase/include/ha_prototypes.h4
-rw-r--r--storage/innobase/include/log0log.h6
-rw-r--r--storage/innobase/lock/lock0lock.cc2
-rw-r--r--storage/innobase/log/log0log.cc4
-rw-r--r--storage/innobase/log/log0recv.cc37
-rw-r--r--storage/innobase/trx/trx0rec.cc41
-rw-r--r--tests/mysql_client_test.c7
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);