polardbxengine/mysql-test/suite/binlog/t/binlog_reset_master_active_...

251 lines
8.1 KiB
Plaintext

################################################################################
# Bug#27041759 RESET MASTER WHILE A TRX IN BGC(AFTER FLUSH) LEAVING SERVER IN
# BAD GTID TATE
#
# Problem: When a transaction is in Binlog group commit, (flush stage is done
# but third stage, commit stage, is not done yet), if some one executes
# RESET MASTER, binlog will not contain the transaction (it will be
# cleared by RESET MASTER), but after the transaction is committed,
# transaction gtid is added to gtid_executed. And this gtid cannot be
# utilized by server again even though the transaction is already
# cleared from the binlog. This leaves the server in bad gtid state.
#
# Step to reproduce:
# ------------------
#
# Step-1) Initial Setup which is required for the test.
# Step-2) Execute a transaction that will wait for a signal
# at various stages of commit. Then execute 'RESET MASTER'
# and observe binlog contents and GTID state. Repeat
# the step when 'global read lock' is already acquired
# by either the same thread or by some other thread
# before executing 'RESET MASTER'.
# Step-3) Test error cases
# Step-4) Cleanup
################################################################################
# Test is independent of Binlog format. One of the three formats is enough
# for testing. Choosing 'Row' format.
--source include/have_binlog_format_row.inc
# Test has debug sync points.
--source include/have_debug.inc
--source include/have_debug_sync.inc
# Some of the .incs in this test are only for gtid enabled test.
--let $include_silent= 1
--echo #
--echo # Step-1) Initial Setup which is required for the test.
--echo #
RESET MASTER;
--source include/save_binlog_position.inc
--let $gtid_mode= `SELECT @@GLOBAL.GTID_MODE`
--let $gtid_event= Anonymous_Gtid
if ($gtid_mode == 'ON')
{
--source include/gtid_step_reset.inc
--let $gtid_event= Gtid
--source include/gtid_utils.inc
}
--echo #
--echo # Step-1.1) Create four client connections.
--echo #
--connect(conn1,localhost,root,,test)
--connect(conn2,localhost,root,,test)
--connect(conn3,localhost,root,,test)
--connect(conn4,localhost,root,,test)
--echo #
--echo # Step-1.2) Create a sample table.
--echo #
CREATE TABLE t1 (i INT);
--echo #
--echo # Step-2) Execute a simple insert transaction that will wait
--echo # for a signal at various stages of transaction commit.
--echo # Execute 'RESET MASTER' when it is waiting for the signal
--echo # and check binlog contents and GTID_EXECUTED (if GTID
--echo # enabled) that they are as expected.
--echo #
# Various Stages:
# i = 1) Before commit takes global read lock.
# (ha_commit_trans_before_acquire_commit_lock)
# i = 2) After taking the lock, before entering into flush stage.
# (bgc_before_flush_stage)
# i = 3) After flush stage but before sync stage.
# (bgc_after_flush_stage_before_sync_stage)
# i = 4) After sync stage but before commit stage
# (bgc_after_sync_stage_before_commit_stage)
# i = 5) After commit stage is done
# (bgc_after_commit_stage_before_rotation)
#
# Also repeat all the above steps when a thread has already acquired
# 'FLUSH TABLES WITH READ LOCK' (either the same thread or some other thread),
# to make sure that 'RESET MASTER' does not give any complaints.
#
# j = 1 , 'RESET MASTER' on a thread that did not execute
# 'FLUSH TABLES WITH READ LOCK'
# j = 2 , 'RESET MASTER' on a thread that already acquired
# 'FLUSH TABLES WITH READ LOCK'
# j = 3 , 'RESET MASTER' on a thread that did not execute
# 'FLUSH TABLES WITH READ LOCK' but some other thread
# has already acquired 'FLUSH TABLES WITH READ LOCK'.
#
--let $j= 1
while ($j <= 3)
{
--let $i= 1
while ($i <= 5)
{
--let $rpl_connection_name= conn1
--source include/rpl_connection.inc
BEGIN;
INSERT INTO t1 VALUES (1);
if ($i == 1)
{
SET debug_sync="ha_commit_trans_before_acquire_commit_lock SIGNAL reached WAIT_FOR insert_continue";
}
if ($i == 2)
{
SET debug_sync="bgc_before_flush_stage SIGNAL reached WAIT_FOR insert_continue";
}
if ($i == 3)
{
SET debug_sync="bgc_after_flush_stage_before_sync_stage SIGNAL reached WAIT_FOR insert_continue";
}
if ($i == 4)
{
SET debug_sync="bgc_after_sync_stage_before_commit_stage SIGNAL reached WAIT_FOR insert_continue";
}
if ($i == 5)
{
SET debug_sync="bgc_after_commit_stage_before_rotation SIGNAL reached WAIT_FOR insert_continue";
}
--send COMMIT
#
# Step-2.1) Wait till insert query reaches debug_sync point and
# generates signal 'reached'.
#
--let $rpl_connection_name= conn2
--source include/rpl_connection.inc
SET debug_sync="now WAIT_FOR reached";
#
# Step-2.2) Now, when transaction is waiting for signal,
# execute 'RESET MASTER'. If this is second iteration (j = 2)
# wrap 'RESET MASTER' with 'FLUSH TABLES WITH READ LOCK'
# and 'UNLOCK TABLES'.
if ($j == 1)
{
--send RESET MASTER
}
if ($j != 1)
{
--send FLUSH TABLES WITH READ LOCK
}
if ($i == 1)
{
--reap
SET debug_sync="now SIGNAL insert_continue";
}
if ($i != 1)
{
--let $rpl_connection_name= conn3
--source include/rpl_connection.inc
--let $wait_condition= SELECT COUNT(*)=1 FROM information_schema.processlist WHERE STATE LIKE 'Waiting for commit lock'
--source include/wait_condition.inc
SET debug_sync="now SIGNAL insert_continue";
--let $rpl_connection_name= conn2
--source include/rpl_connection.inc
--reap
}
if ($j == 2)
{
RESET MASTER;
UNLOCK TABLES;
}
if ($j == 3)
{
--let $rpl_connection_name= conn4
--source include/rpl_connection.inc
RESET MASTER;
--let $rpl_connection_name= conn2
--source include/rpl_connection.inc
UNLOCK TABLES;
}
#
# Step-2.3) Wait till the transaction is finished.
#
--let $rpl_connection_name= conn1
--source include/rpl_connection.inc
--reap
#
# Step-2.4) Check binlog contents and GTID state (if GTID enabled)
# If 'RESET MASTER' is executed before the transaction
# commit acquires 'global read lock' (i = 1 iteration),
# then binlog should contain the transaction events
# and one GTID should be utilized.
#
# If transaction commit is already in BGC (after acquiring
# 'global read lock', then 'RESET MASTER' will wait for
# the transaction to complete and then will do it's work.
# In this case (i = 2, 3, 4, 5), binlog should be empty
# and no GTIDs are utilized.
if ($i == 1)
{
--let $event_sequence= $gtid_event # !Begin # !Insert # !Commit
--source include/assert_binlog_events.inc
if ($gtid_mode == 'ON')
{
--let $gtid_step_count= 1
--source include/gtid_step_assert.inc
}
}
if ($i != 1)
{
--let $event_sequence= ()
--source include/assert_binlog_events.inc
if ($gtid_mode == 'ON')
{
--let $gtid_step_count= 0
--source include/gtid_step_assert.inc
}
}
--echo #
--echo # Step-2.4) Reset the debug signals for the next iteration
--echo #
--let $rpl_connection_name= conn2
--source include/rpl_connection.inc
SET debug_sync="RESET";
--inc $i
}
--inc $j
}
--echo #
--echo # Step-3) Check that 'RESET MASTER' fails if it is executed from a
--echo # session that has already acquired locks on a table.
--echo #
LOCK TABLE t1 READ;
--error ER_LOCK_OR_ACTIVE_TRANSACTION
RESET MASTER;
UNLOCK TABLES;
LOCK TABLE t1 WRITE;
--error ER_LOCK_OR_ACTIVE_TRANSACTION
RESET MASTER;
UNLOCK TABLES;
--echo # Step-4) Cleanup
--echo #
DROP TABLE t1;
if ($gtid_mode == 'ON')
{
--source include/gtid_utils_end.inc
}
--disconnect conn1
--disconnect conn2
--disconnect conn3
--disconnect conn4