From 34e8585437abc862f31aeb1a4022ef278a4af6f0 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Wed, 16 Aug 2023 11:57:34 +0200 Subject: [PATCH 1/4] MDEV-29974: Missed kill waiting for worker queues to drain When the SQL driver thread goes to wait for room in the parallel slave worker queue, there was a race where a kill at the right moment could be ignored and the wait proceed uninterrupted by the kill. Fix by moving the THD::check_killed() to occur _after_ doing ENTER_COND(). This bug was seen as sporadic failure of the testcase rpl.rpl_parallel (rpl.rpl_parallel_gco_wait_kill since 10.5), with "Slave stopped with wrong error code". Signed-off-by: Kristian Nielsen --- sql/rpl_parallel.cc | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index ba5cf54e673..3bd27c73932 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -2281,21 +2281,6 @@ rpl_parallel_entry::choose_thread(rpl_group_info *rgi, bool *did_enter_cond, /* The thread is ready to queue into. */ break; } - else if (unlikely(rli->sql_driver_thd->check_killed(1))) - { - unlock_or_exit_cond(rli->sql_driver_thd, &thr->LOCK_rpl_thread, - did_enter_cond, old_stage); - my_error(ER_CONNECTION_KILLED, MYF(0)); -#ifdef ENABLED_DEBUG_SYNC - DBUG_EXECUTE_IF("rpl_parallel_wait_queue_max", - { - debug_sync_set_action(rli->sql_driver_thd, - STRING_WITH_LEN("now SIGNAL wait_queue_killed")); - };); -#endif - slave_output_error_info(rgi, rli->sql_driver_thd); - return NULL; - } else { /* @@ -2323,6 +2308,23 @@ rpl_parallel_entry::choose_thread(rpl_group_info *rgi, bool *did_enter_cond, old_stage); *did_enter_cond= true; } + + if (unlikely(rli->sql_driver_thd->check_killed(1))) + { + unlock_or_exit_cond(rli->sql_driver_thd, &thr->LOCK_rpl_thread, + did_enter_cond, old_stage); + my_error(ER_CONNECTION_KILLED, MYF(0)); +#ifdef ENABLED_DEBUG_SYNC + DBUG_EXECUTE_IF("rpl_parallel_wait_queue_max", + { + debug_sync_set_action(rli->sql_driver_thd, + STRING_WITH_LEN("now SIGNAL wait_queue_killed")); + };); +#endif + slave_output_error_info(rgi, rli->sql_driver_thd); + return NULL; + } + mysql_cond_wait(&thr->COND_rpl_thread_queue, &thr->LOCK_rpl_thread); } } From 44df6f35aa690cdac0409b7853468891ade33cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 17 Aug 2023 10:31:28 +0300 Subject: [PATCH 2/4] MDEV-31875 ROW_FORMAT=COMPRESSED table: InnoDB: ... Only 0 bytes read buf_read_ahead_random(), buf_read_ahead_linear(): Avoid read-ahead of the last page(s) of ROW_FORMAT=COMPRESSED tablespaces that use a page size of 1024 or 2048 bytes. We invoke os_file_set_size() on integer multiples of 4096 bytes in order to be compatible with the requirements of innodb_flush_method=O_DIRECT regardless of the physical block size of the underlying storage. This change must be null-merged to MariaDB Server 10.5 and later. There, out-of-bounds read-ahead should be handled gracefully by simply discarding the buffer page that had been allocated. Tested by: Matthias Leich --- storage/innobase/buf/buf0rea.cc | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc index 1ea3070cbda..5ea177dbbd0 100644 --- a/storage/innobase/buf/buf0rea.cc +++ b/storage/innobase/buf/buf0rea.cc @@ -266,8 +266,24 @@ buf_read_ahead_random(const page_id_t page_id, ulint zip_size, bool ibuf) * buf_read_ahead_random_area; if (fil_space_t* space = fil_space_acquire(page_id.space())) { - high = space->max_page_number_for_io(high); + ulint space_size = space->committed_size; + ulint zip_size = space->zip_size(); space->release(); + /* Avoid read-ahead of the last page(s) of + small-page-size ROW_FORMAT=COMPRESSED tablespaces, + because fil_space_extend_must_retry() would invoke + os_file_set_size() on integer multiples of 4 KiB. */ + switch (UNIV_EXPECT(zip_size, 0)) { + case 1024: + space_size &= ~ulint{3}; + break; + case 2048: + space_size &= ~ulint{1}; + break; + } + if (high > space_size) { + high = space_size; + } } else { return(0); } @@ -531,7 +547,20 @@ buf_read_ahead_linear(const page_id_t page_id, ulint zip_size, bool ibuf) if (fil_space_t* space = fil_space_acquire(page_id.space())) { space_size = space->committed_size; + ulint zip_size = space->zip_size(); space->release(); + /* Avoid read-ahead of the last page(s) of + small-page-size ROW_FORMAT=COMPRESSED tablespaces, + because fil_space_extend_must_retry() would invoke + os_file_set_size() on integer multiples of 4 KiB. */ + switch (UNIV_EXPECT(zip_size, 0)) { + case 1024: + space_size &= ~ulint{3}; + break; + case 2048: + space_size &= ~ulint{1}; + break; + } if (high > space_size) { /* The area is not whole */ From 518fe519887cfb354cd463afa76077df49e96057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 17 Aug 2023 10:31:44 +0300 Subject: [PATCH 3/4] MDEV-31254 InnoDB: Trying to read doublewrite buffer page buf_read_page_low(): Remove an error message that could be triggered by buf_read_ahead_linear() or buf_read_ahead_random(). This is a backport of commit c9eff1a144ba44846373660a30d342d3f0dc91a5 from MariaDB Server 10.5. --- storage/innobase/buf/buf0rea.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc index 5ea177dbbd0..9e06fc9cf81 100644 --- a/storage/innobase/buf/buf0rea.cc +++ b/storage/innobase/buf/buf0rea.cc @@ -128,9 +128,6 @@ buf_read_page_low( if (page_id.space() == TRX_SYS_SPACE && buf_dblwr_page_inside(page_id.page_no())) { - - ib::error() << "Trying to read doublewrite buffer page " - << page_id; return(0); } From 5a8a8fc9538861f699805db4baddecdb87af5052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 17 Aug 2023 10:31:55 +0300 Subject: [PATCH 4/4] MDEV-31928 Assertion xid ... < 128 failed in trx_undo_write_xid() trx_undo_write_xid(): Correct an off-by-one error in a debug assertion. --- mysql-test/suite/innodb/r/innodb-xa.result | 27 +++++++++++++++++ mysql-test/suite/innodb/t/innodb-xa.test | 35 +++++++++++++++++++++- storage/innobase/trx/trx0undo.cc | 2 +- 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-xa.result b/mysql-test/suite/innodb/r/innodb-xa.result index 6eae842b14c..6651bd5090d 100644 --- a/mysql-test/suite/innodb/r/innodb-xa.result +++ b/mysql-test/suite/innodb/r/innodb-xa.result @@ -15,3 +15,30 @@ xa prepare 'xid2'; release savepoint `sv1`; xa commit 'xid2'; drop table t1; +# +# MDEV-31928 Assertion xid ... < 128 failed in trx_undo_write_xid() +# +CREATE TABLE t (a INT PRIMARY KEY) ENGINE=INNODB; +XA START 'gtrid_67890123456789012345678901234567890123456789012345678901234','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1234567890' at line 1 +XA START 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_67890123456789012345678901234567890123456789012345678901234',1234567890; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1234567890' at line 1 +XA START 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +INSERT INTO t VALUES(1); +XA END 'gtrid_67890123456789012345678901234567890123456789012345678901234','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1234567890' at line 1 +XA END 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_67890123456789012345678901234567890123456789012345678901234',1234567890; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1234567890' at line 1 +XA END 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +XA PREPARE 'gtrid_67890123456789012345678901234567890123456789012345678901234','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1234567890' at line 1 +XA PREPARE 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_67890123456789012345678901234567890123456789012345678901234',1234567890; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1234567890' at line 1 +XA PREPARE 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +XA COMMIT 'gtrid_67890123456789012345678901234567890123456789012345678901234','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1234567890' at line 1 +XA COMMIT 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_67890123456789012345678901234567890123456789012345678901234',1234567890; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1234567890' at line 1 +XA COMMIT 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +DROP TABLE t; +# End of 10.4 tests diff --git a/mysql-test/suite/innodb/t/innodb-xa.test b/mysql-test/suite/innodb/t/innodb-xa.test index d94cd75aa14..9eb5848b04d 100644 --- a/mysql-test/suite/innodb/t/innodb-xa.test +++ b/mysql-test/suite/innodb/t/innodb-xa.test @@ -1,6 +1,6 @@ --source include/have_innodb.inc ---disable_abort_on_error +--error ER_XAER_NOTA xa rollback 'xid2'; drop table if exists t1; create table t1(a int)engine=innodb; @@ -9,9 +9,42 @@ xa start 'xid2'; insert into `t1` values (1); savepoint `sv1`; xa end 'xid2'; +--error ER_XAER_RMFAIL start transaction; xa prepare 'xid2'; release savepoint `sv1`; xa commit 'xid2'; drop table t1; +-- echo # +-- echo # MDEV-31928 Assertion xid ... < 128 failed in trx_undo_write_xid() +-- echo # + +CREATE TABLE t (a INT PRIMARY KEY) ENGINE=INNODB; +--error ER_PARSE_ERROR +XA START 'gtrid_67890123456789012345678901234567890123456789012345678901234','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +--error ER_PARSE_ERROR +XA START 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_67890123456789012345678901234567890123456789012345678901234',1234567890; +XA START 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; + +INSERT INTO t VALUES(1); + +--error ER_PARSE_ERROR +XA END 'gtrid_67890123456789012345678901234567890123456789012345678901234','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +--error ER_PARSE_ERROR +XA END 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_67890123456789012345678901234567890123456789012345678901234',1234567890; +XA END 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +--error ER_PARSE_ERROR +XA PREPARE 'gtrid_67890123456789012345678901234567890123456789012345678901234','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +--error ER_PARSE_ERROR +XA PREPARE 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_67890123456789012345678901234567890123456789012345678901234',1234567890; +XA PREPARE 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +--error ER_PARSE_ERROR +XA COMMIT 'gtrid_67890123456789012345678901234567890123456789012345678901234','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; +--error ER_PARSE_ERROR +XA COMMIT 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_67890123456789012345678901234567890123456789012345678901234',1234567890; +XA COMMIT 'gtrid_6789012345678901234567890123456789012345678901234567890123','bqual_6789012345678901234567890123456789012345678901234567890123',1234567890; + +DROP TABLE t; + +-- echo # End of 10.4 tests diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index 8768b934dba..917f662eaa5 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -665,7 +665,7 @@ trx_undo_write_xid( { DBUG_ASSERT(xid->gtrid_length >= 0); DBUG_ASSERT(xid->bqual_length >= 0); - DBUG_ASSERT(xid->gtrid_length + xid->bqual_length < XIDDATASIZE); + DBUG_ASSERT(xid->gtrid_length + xid->bqual_length <= XIDDATASIZE); mlog_write_ulint(log_hdr + TRX_UNDO_XA_FORMAT, static_cast(xid->formatID),