mariadb/mysql-test/suite/innodb/t/purge_pessimistic.test
Marko Mäkelä 19acb0257e MDEV-35508 Race condition between purge and secondary index INSERT or UPDATE
row_purge_remove_sec_if_poss_leaf(): If there is an active transaction
that is not newer than PAGE_MAX_TRX_ID, return the bogus value 1
so that row_purge_remove_sec_if_poss_tree() is guaranteed to recheck if
the record needs to be purged. It could be the case that an active
transaction would insert this record between the time this check
completed and row_purge_remove_sec_if_poss_tree() acquired a latch
on the secondary index leaf page again.

row_purge_del_mark_error(), row_purge_check(): Some unlikely code
refactored into separate non-inline functions.

trx_sys_t::find_same_or_older_low(): Move the unlikely and bulky
part of trx_sys_t::find_same_or_older() to a non-inline function.

trx_sys_t::find_same_or_older_in_purge(): A variant of
trx_sys_t::find_same_or_older() for use in the purge subsystem,
with potential concurrent access of the same trx_t object from
multiple threads.

trx_t::max_inactive_id_atomic: An Atomic_relaxed alias of the
regular data field trx_t::max_inactive_id, which we
use on systems that have native 64-bit loads or stores.
On any 64-bit system that seems to be supported by GCC, Clang or MSVC,
relaxed atomic loads and stores use the regular load and store
instructions. On -march=i686 the 64-bit atomic loads and stores
would use an XMM register.

This fixes a regression that had been introduced in
commit b7b9f3ce82 (MDEV-34515).
There would be messages
[ERROR] InnoDB: tried to purge non-delete-marked record in index
in the server error log, and an assertion ut_ad(0) would cause a
crash of debug instrumented builds. This could also cause incorrect
results for MVCC reads and corrupted secondary indexes.

The debug instrumented test case was written by Debarun Banerjee.

Reviewed by: Debarun Banerjee
2024-11-29 10:44:38 +02:00

51 lines
1.3 KiB
Text

--source include/have_innodb.inc
--source include/count_sessions.inc
--source include/have_debug.inc
--source include/have_debug_sync.inc
--source include/not_embedded.inc
--echo #
--echo # MDEV-35508: Race condition between purge and secondary index INSERT or UPDATE
--echo #
SET @old_debug_dbug = @@global.debug_dbug;
CREATE TABLE t1(col1 INT PRIMARY KEY, col2 int, KEY k1(col2)) ENGINE=Innodb;
INSERT INTO t1 VALUES(1, 100);
CREATE TABLE t2(col1 INT PRIMARY KEY) Engine=Innodb;
--source include/wait_all_purged.inc
START TRANSACTION;
INSERT INTO t2 VALUES(10);
SET DEBUG_SYNC='RESET';
SET GLOBAL debug_dbug= "+d,btr_force_pessimistic_delete";
SET GLOBAL debug_dbug= "+d,enable_row_purge_sec_tree_sync";
--connect (con1,localhost,root)
UPDATE t1 SET col2 = 200 WHERE col1 = 1;
--connection default
SET DEBUG_SYNC= 'now WAIT_FOR purge_sec_tree_begin';
SET GLOBAL debug_dbug= "-d,enable_row_purge_sec_tree_sync";
UPDATE t1 SET col2 = 100 WHERE col1 = 1;
SET DEBUG_SYNC= 'now SIGNAL purge_sec_tree_execute';
COMMIT;
--source include/wait_all_purged.inc
--disconnect con1
--source include/wait_until_count_sessions.inc
SELECT * FROM t1;
CHECK TABLE t1;
DROP TABLE t1;
SELECT * FROM t2;
DROP TABLE t2;
SET @@GLOBAL.debug_dbug = @old_debug_dbug;
SET DEBUG_SYNC='RESET';