|
| 1 | +################################################################################ |
| 2 | +# BUG#25379659 MASTER MAY BINLOG A WRONG LAST_COMMITED |
| 3 | +# |
| 4 | +# Transactions could binlog a last_commited smaller than expected. With the |
| 5 | +# wrong last_commited values, the transactions which sould be applied |
| 6 | +# sequentially could be applied parallel. That caused applier errors or data |
| 7 | +# inconsistency. |
| 8 | +# |
| 9 | +# When committing a transaction, its last_commited is set to the value of |
| 10 | +# max_committed_transaction. max_committed_transaction is the maximum |
| 11 | +# sequence_number of committed transactions. It is maintained just before |
| 12 | +# committing each transaction to engine. If its sequence_number is not |
| 13 | +# SEQ_UNINIT then updates max_committed_transaction accordingly. |
| 14 | +# |
| 15 | +# However, it checked wrong sequence_number(the sequence_number of the |
| 16 | +# leader thread's transaction instead of the sequence_number of the transaction). |
| 17 | +# That caused that max_committed_transaction was only updated in time for leader |
| 18 | +# thread's transaction. The update for following transactions were delay to |
| 19 | +# finish_commit() which was after the transaction commited to engine. |
| 20 | +# |
| 21 | +# The test verifys last_committed is corret in the bug situation. |
| 22 | +# |
| 23 | +# Step 1. Use debug sync to gurantee that commit queue has two transactions. |
| 24 | +# Step 2. Use debug sync to pause the second transaction when it enters |
| 25 | +# finshi_commit() |
| 26 | +# Step 3. Execute a transaction and check if its last_committed is correct. |
| 27 | +################################################################################ |
| 28 | +--source include/have_binlog_format_statement.inc |
| 29 | +--source include/have_debug_sync.inc |
| 30 | + |
| 31 | +# Reset sequence_number and last_committed, so we can check the exact number |
| 32 | +# Make sure it starts from master-bin.000001 |
| 33 | +RESET MASTER; |
| 34 | + |
| 35 | +CREATE TABLE t1(c1 INT PRIMARY KEY, c2 INT) ENGINE = InnoDB; |
| 36 | + |
| 37 | +# Make the INSERT to wait for another INSERT into the flush queue |
| 38 | +SET DEBUG_SYNC = "bgc_after_enrolling_for_commit_stage |
| 39 | + SIGNAL insert1_ready WAIT_FOR continue_commit_stage"; |
| 40 | +--send INSERT INTO t1 VALUES(1, 1) |
| 41 | + |
| 42 | +--connect(conn1, localhost, root) |
| 43 | +--connect(conn2, localhost, root) |
| 44 | +--connection conn1 |
| 45 | + |
| 46 | +# Make sure above INSERT is the leader |
| 47 | +SET DEBUG_SYNC = "now WAIT_FOR insert1_ready"; |
| 48 | +# Record the INSERT's binlog position |
| 49 | +--let $binlog_pos= query_get_value(SHOW MASTER STATUS, Position, 1) |
| 50 | + |
| 51 | +# Pause the INSERT when it enters finishi_commit() |
| 52 | +SET DEBUG_SYNC = "reached_finish_commit WAIT_FOR insert2_finish"; |
| 53 | +--send INSERT INTO t1 VALUES(2, 1) |
| 54 | + |
| 55 | +# Wait until above INSERT is binlogged |
| 56 | +--connection conn2 |
| 57 | +--let $show_statement= SHOW MASTER STATUS |
| 58 | +--let $field= Position |
| 59 | +--let $condition= != '$binlog_pos' |
| 60 | +--source include/wait_show_condition.inc |
| 61 | + |
| 62 | +# Signal insert1 to finish the commit group |
| 63 | +SET DEBUG_SYNC = "now SIGNAL continue_commit_stage"; |
| 64 | +--connection default |
| 65 | +--reap |
| 66 | + |
| 67 | +UPDATE t1 SET c2 = 2 WHERE c1 = 2; |
| 68 | + |
| 69 | +SET DEBUG_SYNC = "now SIGNAL insert2_finish"; |
| 70 | +--connection conn1 |
| 71 | +--reap |
| 72 | + |
| 73 | +--connection default |
| 74 | +# INSERT(2,1): sequence_number = 3 |
| 75 | +# UPDATE: sequence_number = 4, last_committed = 3 |
| 76 | + |
| 77 | +--let $binlog_file= master-bin.000001 |
| 78 | +--let $logical_timestamps= 3 4 |
| 79 | +--source include/assert_logical_timestamps.inc |
| 80 | + |
| 81 | +DROP TABLE t1; |
0 commit comments