|
| 1 | +--source include/have_innodb.inc |
| 2 | +--source include/have_debug.inc |
| 3 | +--source include/have_debug_sync.inc |
| 4 | +--source include/have_binlog_format_mixed.inc |
| 5 | +--source include/count_sessions.inc |
| 6 | + |
| 7 | +# MDEV-30010 merely adds is a Read-Committed version MDEV-30225 test |
| 8 | +# solely to prove the RC isolation yields ROW binlog format as it is |
| 9 | +# supposed to: |
| 10 | +# https://mariadb.com/kb/en/unsafe-statements-for-statement-based-replication/#isolation-levels. |
| 11 | +# The original MDEV-30225 test is adapted to the RC to create |
| 12 | +# a similar safisticated scenario which does not lead to any deadlock though. |
| 13 | + |
| 14 | +--connect (pause_purge,localhost,root) |
| 15 | +START TRANSACTION WITH CONSISTENT SNAPSHOT; |
| 16 | + |
| 17 | +--connection default |
| 18 | +CREATE TABLE t (pk int PRIMARY KEY, sk INT UNIQUE) ENGINE=InnoDB; |
| 19 | +INSERT INTO t VALUES (10, 100); |
| 20 | + |
| 21 | +--connect (con1,localhost,root) |
| 22 | +BEGIN; # trx 0 |
| 23 | +SELECT * FROM t WHERE sk = 100 FOR UPDATE; |
| 24 | + |
| 25 | +--connect (con2,localhost,root) |
| 26 | +SET DEBUG_SYNC="lock_wait_suspend_thread_enter SIGNAL insert_wait_started"; |
| 27 | +# trx 1 is locked on try to read the record in secondary index during duplicates |
| 28 | +# check. It's the first in waiting queue, that's why it will be woken up firstly |
| 29 | +# when trx 0 commits. |
| 30 | +--send INSERT INTO t VALUES (5, 100) # trx 1 |
| 31 | + |
| 32 | +--connect (con3,localhost,root) |
| 33 | +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; |
| 34 | +SET DEBUG_SYNC="now WAIT_FOR insert_wait_started"; |
| 35 | +SET DEBUG_SYNC="lock_wait_suspend_thread_enter SIGNAL delete_started_waiting"; |
| 36 | +# trx 2 can delete (5, 100) on master, but not on slave, as on slave trx 1 |
| 37 | +# can insert (5, 100) after trx 2 positioned it's cursor. Trx 2 lock is placed |
| 38 | +# in waiting queue after trx 1 lock, but its persistent cursor position was |
| 39 | +# stored on (100, 10) record in secondary index before suspending. After trx 1 |
| 40 | +# is committed, trx 2 will restore persistent cursor position on (100, 10). As |
| 41 | +# (100, 5) secondary index record was inserted before (100, 10) in logical |
| 42 | +# order, and (100, 10) record is delete-marked, trx 2 just continues scanning. |
| 43 | +# |
| 44 | +# Note. There can be several records with the same key in unique secondary |
| 45 | +# index, but only one of them must be non-delete-marked. That's why when we do |
| 46 | +# point query, cursor position is set in the first record in logical order, and |
| 47 | +# then records are iterated until either non-delete-marked record is found or |
| 48 | +# all records with the same unique fields are iterated. |
| 49 | + |
| 50 | +# to prepare showing interesting binlog events |
| 51 | +--let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1) |
| 52 | +BEGIN; |
| 53 | +--send UPDATE t SET sk = 200 WHERE sk = 100; # trx 2 |
| 54 | + |
| 55 | +--connection con1 |
| 56 | +SET DEBUG_SYNC="now WAIT_FOR delete_started_waiting"; |
| 57 | +DELETE FROM t WHERE sk=100; # trx 0 |
| 58 | +COMMIT; |
| 59 | +--disconnect con1 |
| 60 | + |
| 61 | +--connection con2 |
| 62 | +--reap |
| 63 | +--disconnect con2 |
| 64 | + |
| 65 | +--connection con3 |
| 66 | +--error 0 |
| 67 | +--reap |
| 68 | +if (`SELECT ROW_COUNT() > 0`) |
| 69 | +{ |
| 70 | + --echo unexpected effective UPDATE |
| 71 | + --die |
| 72 | +} |
| 73 | +--echo must be logged in ROW format as the only event of trx 2 (con3) |
| 74 | +INSERT INTO t VALUES (11, 101); |
| 75 | +COMMIT; |
| 76 | +--source include/show_binlog_events.inc |
| 77 | +--disconnect con3 |
| 78 | + |
| 79 | +--connection default |
| 80 | +# If the bug is not fixed, we will see the row inserted by trx 1 here. This can |
| 81 | +# cause duplicate key error on slave, when some other trx tries in insert row |
| 82 | +# with the same secondary key, as was inserted by trx 1, and not deleted by trx |
| 83 | +# 2. |
| 84 | +SELECT * FROM t; |
| 85 | + |
| 86 | +--disconnect pause_purge |
| 87 | +SET DEBUG_SYNC="RESET"; |
| 88 | +DROP TABLE t; |
| 89 | +--source include/wait_until_count_sessions.inc |
0 commit comments