-
Notifications
You must be signed in to change notification settings - Fork 713
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Stop slave immediately in MTS if partial trx in the relay log can be …
…rollbacked Summary: In MTS stop slave can take a minute to complete if the last transaction is partially downloaded from the master. The slave waits for a minute for the master to send the rest of the trx and then finally gives up. Strictly, this wait is only required if the partial trx cannot be rollbacked safely (e.g. trx on non-transactional engine, DDLs etc.). This change checks if there are no jobs queued in the worker threads and if the partial trx can be rollbacked, if yes, it immediately stops the slave. Reviewed By: tianx Differential Revision: D5130797 fbshipit-source-id: 4f1f0b6
- Loading branch information
1 parent
754aa79
commit cd39ae1
Showing
8 changed files
with
327 additions
and
1 deletion.
There are no files selected for viewing
111 changes: 111 additions & 0 deletions
111
mysql-test/suite/rpl/r/rpl_stop_slave_partial_trx.result
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
include/master-slave.inc | ||
Warnings: | ||
Note #### Sending passwords in plain text without SSL/TLS is extremely insecure. | ||
Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information. | ||
[connection master] | ||
call mtr.add_suppression("The slave coordinator and worker threads are stopped, possibly leaving data in inconsistent state"); | ||
create database d1; | ||
create database d2; | ||
create database d3; | ||
create table d1.t1 (a int) engine=innodb; | ||
create table d2.t2 (a int) engine=myisam; | ||
create table d3.t3 (a int) engine=innodb; | ||
lock tables d1.t1 read; | ||
insert into d1.t1 values(1); | ||
insert into d1.t1 values(1); | ||
insert into d1.t1 values(1); | ||
insert into d1.t1 values(1); | ||
insert into d1.t1 values(1); | ||
set global debug= '+d,dump_thread_wait_after_send_write_rows'; | ||
insert into d2.t2 values(1); | ||
unlock tables; | ||
set @start=now(); | ||
stop slave; | ||
select timestampdiff(SECOND, @start, now()) >= 60; | ||
timestampdiff(SECOND, @start, now()) >= 60 | ||
1 | ||
start slave; | ||
SET DEBUG_SYNC= 'now SIGNAL signal.continue'; | ||
SET DEBUG_SYNC= 'RESET'; | ||
set @@global.debug= '-d,dump_thread_wait_after_send_write_rows'; | ||
"Tables on master:" | ||
connection master | ||
select * from d1.t1; | ||
a | ||
1 | ||
1 | ||
1 | ||
1 | ||
1 | ||
select * from d2.t2; | ||
a | ||
1 | ||
select * from d3.t3; | ||
a | ||
"Tables on slave:" | ||
connection slave | ||
select * from d1.t1; | ||
a | ||
1 | ||
1 | ||
1 | ||
1 | ||
1 | ||
select * from d2.t2; | ||
a | ||
1 | ||
select * from d3.t3; | ||
a | ||
delete from d1.t1; | ||
delete from d2.t2; | ||
delete from d3.t3; | ||
lock tables d1.t1 read; | ||
insert into d1.t1 values(1); | ||
insert into d1.t1 values(1); | ||
insert into d1.t1 values(1); | ||
insert into d1.t1 values(1); | ||
insert into d1.t1 values(1); | ||
set global debug= '+d,dump_thread_wait_after_send_write_rows'; | ||
insert into d3.t3 values(1); | ||
unlock tables; | ||
set @start=now(); | ||
stop slave; | ||
select timestampdiff(SECOND, @start, now()) < 60; | ||
timestampdiff(SECOND, @start, now()) < 60 | ||
1 | ||
start slave; | ||
SET DEBUG_SYNC= 'now SIGNAL signal.continue'; | ||
SET DEBUG_SYNC= 'RESET'; | ||
set @@global.debug= '-d,dump_thread_wait_after_send_write_rows'; | ||
"Tables on master:" | ||
connection master | ||
select * from d1.t1; | ||
a | ||
1 | ||
1 | ||
1 | ||
1 | ||
1 | ||
select * from d2.t2; | ||
a | ||
select * from d3.t3; | ||
a | ||
1 | ||
"Tables on slave:" | ||
connection slave | ||
select * from d1.t1; | ||
a | ||
1 | ||
1 | ||
1 | ||
1 | ||
1 | ||
select * from d2.t2; | ||
a | ||
select * from d3.t3; | ||
a | ||
1 | ||
drop database d1; | ||
drop database d2; | ||
drop database d3; | ||
include/rpl_end.inc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
--slave_parallel_workers=8 --enforce-gtid-consistency --gtid-mode=ON --log-bin | ||
--log-slave-updates |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
--slave_parallel_workers=8 --enforce-gtid-consistency --gtid-mode=ON --log-bin | ||
--log-slave-updates |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
source include/master-slave.inc; | ||
source include/have_debug.inc; | ||
source include/have_debug_sync.inc; | ||
source include/have_binlog_format_row.inc; | ||
|
||
call mtr.add_suppression("The slave coordinator and worker threads are stopped, possibly leaving data in inconsistent state"); | ||
|
||
# Create schema | ||
connection master; | ||
create database d1; | ||
create database d2; | ||
create database d3; | ||
create table d1.t1 (a int) engine=innodb; | ||
create table d2.t2 (a int) engine=myisam; # non-transactional engine | ||
create table d3.t3 (a int) engine=innodb; # transactional engine | ||
sync_slave_with_master; | ||
|
||
|
||
|
||
## Test 1: STOP SLAVE when there are pending jobs in the worker queues and there | ||
## is a partial transaction on a non-transactional table. The slave should wait | ||
## for 1 minute to complete the partial transaction before giving up. | ||
|
||
# Block all d1.t1 transactions on the slave | ||
connection slave; | ||
lock tables d1.t1 read; | ||
|
||
# Generate some load, all of these will be blocked in the slave worker queue | ||
connection master; | ||
let $num_inserts=5; | ||
while ($num_inserts) | ||
{ | ||
insert into d1.t1 values(1); | ||
dec $num_inserts; | ||
} | ||
|
||
# This will stop the dump thread before sending the entire group | ||
set global debug= '+d,dump_thread_wait_after_send_write_rows'; | ||
insert into d2.t2 values(1); | ||
|
||
# wait for the dump thread reach the sync point | ||
--let $wait_condition= select count(*)=1 from information_schema.processlist where state LIKE '%debug sync point%' and command like 'Binlog Dump%' | ||
--source include/wait_condition.inc | ||
|
||
connection slave; | ||
# unblock d1.t1 | ||
unlock tables; | ||
|
||
# This should take at least a minute because the trx on t2 is not completely downloaded and cannot be rollbacked safely | ||
set @start=now(); | ||
stop slave; | ||
select timestampdiff(SECOND, @start, now()) >= 60; | ||
start slave; | ||
|
||
connection master; | ||
SET DEBUG_SYNC= 'now SIGNAL signal.continue'; | ||
# wait for the dump thread to come out of the waiting phase before resetting the signals | ||
--let $wait_condition= select count(*)=0 from information_schema.processlist where state LIKE '%debug sync point%' and command='Binlog Dump' | ||
--source include/wait_condition.inc | ||
SET DEBUG_SYNC= 'RESET'; | ||
|
||
connection master; | ||
set @@global.debug= '-d,dump_thread_wait_after_send_write_rows'; | ||
sync_slave_with_master; | ||
|
||
# Verification | ||
connection master; | ||
echo "Tables on master:" | ||
connection master; | ||
select * from d1.t1; | ||
select * from d2.t2; | ||
select * from d3.t3; | ||
echo "Tables on slave:" | ||
connection slave; | ||
select * from d1.t1; | ||
select * from d2.t2; | ||
select * from d3.t3; | ||
|
||
# cleanup | ||
connection master; | ||
delete from d1.t1; | ||
delete from d2.t2; | ||
delete from d3.t3; | ||
sync_slave_with_master; | ||
|
||
|
||
|
||
## Test 2: STOP SLAVE when there are pending jobs in the worker queues and there | ||
## is a partial transaction on a transactional table. The slave should stop | ||
## immidiately after completing all pending full transactions. | ||
|
||
# Block all d1.t1 transactions on the slave | ||
connection slave; | ||
lock tables d1.t1 read; | ||
|
||
# Generate some load, all of these will be blocked in the slave worker queue | ||
connection master; | ||
let $num_inserts=5; | ||
while ($num_inserts) | ||
{ | ||
insert into d1.t1 values(1); | ||
dec $num_inserts; | ||
} | ||
|
||
# This will stop the dump thread before sending the entire group | ||
set global debug= '+d,dump_thread_wait_after_send_write_rows'; | ||
insert into d3.t3 values(1); | ||
|
||
# wait for the dump thread reach the sync point | ||
--let $wait_condition= select count(*)=1 from information_schema.processlist where state LIKE '%debug sync point%' and command like 'Binlog Dump%' | ||
--source include/wait_condition.inc | ||
|
||
connection slave; | ||
# unblock d1.t1 | ||
unlock tables; | ||
|
||
# Since the partial transaction is on a transactional table the slave should | ||
# stop as soon as is completes all pending full transactions | ||
set @start=now(); | ||
stop slave; | ||
select timestampdiff(SECOND, @start, now()) < 60; | ||
start slave; | ||
|
||
connection master; | ||
SET DEBUG_SYNC= 'now SIGNAL signal.continue'; | ||
# wait for the dump thread to come out of the waiting phase before resetting the signals | ||
--let $wait_condition= select count(*)=0 from information_schema.processlist where state LIKE '%debug sync point%' and command='Binlog Dump' | ||
--source include/wait_condition.inc | ||
SET DEBUG_SYNC= 'RESET'; | ||
|
||
connection master; | ||
set @@global.debug= '-d,dump_thread_wait_after_send_write_rows'; | ||
sync_slave_with_master; | ||
|
||
# Verification | ||
connection master; | ||
echo "Tables on master:" | ||
connection master; | ||
select * from d1.t1; | ||
select * from d2.t2; | ||
select * from d3.t3; | ||
echo "Tables on slave:" | ||
connection slave; | ||
select * from d1.t1; | ||
select * from d2.t2; | ||
select * from d3.t3; | ||
|
||
# final cleanup | ||
connection master; | ||
drop database d1; | ||
drop database d2; | ||
drop database d3; | ||
sync_slave_with_master; | ||
|
||
|
||
source include/rpl_end.inc; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters