Description:
If the database run as --skip-log-bin, the steps to commit in innodb are as follows:
1. The mtr of modifying undo log header commits.
2. Erase the trx_id from rw_trx_ids
3. Wait for the redo sync.
If there is a session run a query after step-2 and before step-3, then it can see the modification of the transaction that hasn't been really committed.
How to repeat:
1. Inject a part of the code and compile it in debug mode.
diff --git a/storage/innobase/log/log0write.cc b/storage/innobase/log/log0write.cc
index 74cbcbe1b03..bf451b71a26 100644
--- a/storage/innobase/log/log0write.cc
+++ b/storage/innobase/log/log0write.cc
@@ -1786,6 +1786,12 @@ static dberr_t log_write_buffer(log_t &log, byte *buffer, size_t buffer_size,
srv_stats.os_log_pending_writes.inc();
+ DBUG_EXECUTE_IF("stop_write_blocks_when_write_redo", {
+ std::this_thread::sleep_for(
+ std::chrono::seconds(2));
+ DBUG_SUICIDE();
+ });
+
/* Now, we know, that we are going to write completed
blocks only (originally or copied and completed). */
const dberr_t err = write_blocks(log, write_buf, write_size, real_offset);
2. Write a MTR test-cases, which might called as trx_text.test
connect (con1,localhost,root,,);
connection default;
create table t1 (id int primary key);
begin;
insert into t1 values (1);
SET GLOBAL DEBUG="+d, stop_write_blocks_when_write_redo";
--send commit
connection con1;
sleep 1;
let $cnt1 = `select count(1) from test.t1`;
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
connection default;
--error 2013
--reap
--enable_reconnect
--source include/wait_until_connected_again.inc
let $cnt2 = `select count(1) from test.t1`;
--let $assert_text= Assert value should not be same
--let $assert_cond = ($cnt1 = $cnt2)
--source include/assert.inc
3. Write a configure file for the testcase, which might be called mysql-test/t/trx_test-master.opt:
--skip-log-bin
4. Run the testcase, and the it will fail.
Description: If the database run as --skip-log-bin, the steps to commit in innodb are as follows: 1. The mtr of modifying undo log header commits. 2. Erase the trx_id from rw_trx_ids 3. Wait for the redo sync. If there is a session run a query after step-2 and before step-3, then it can see the modification of the transaction that hasn't been really committed. How to repeat: 1. Inject a part of the code and compile it in debug mode. diff --git a/storage/innobase/log/log0write.cc b/storage/innobase/log/log0write.cc index 74cbcbe1b03..bf451b71a26 100644 --- a/storage/innobase/log/log0write.cc +++ b/storage/innobase/log/log0write.cc @@ -1786,6 +1786,12 @@ static dberr_t log_write_buffer(log_t &log, byte *buffer, size_t buffer_size, srv_stats.os_log_pending_writes.inc(); + DBUG_EXECUTE_IF("stop_write_blocks_when_write_redo", { + std::this_thread::sleep_for( + std::chrono::seconds(2)); + DBUG_SUICIDE(); + }); + /* Now, we know, that we are going to write completed blocks only (originally or copied and completed). */ const dberr_t err = write_blocks(log, write_buf, write_size, real_offset); 2. Write a MTR test-cases, which might called as trx_text.test connect (con1,localhost,root,,); connection default; create table t1 (id int primary key); begin; insert into t1 values (1); SET GLOBAL DEBUG="+d, stop_write_blocks_when_write_redo"; --send commit connection con1; sleep 1; let $cnt1 = `select count(1) from test.t1`; --exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect connection default; --error 2013 --reap --enable_reconnect --source include/wait_until_connected_again.inc let $cnt2 = `select count(1) from test.t1`; --let $assert_text= Assert value should not be same --let $assert_cond = ($cnt1 = $cnt2) --source include/assert.inc 3. Write a configure file for the testcase, which might be called mysql-test/t/trx_test-master.opt: --skip-log-bin 4. Run the testcase, and the it will fail.