mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-04 12:56:14 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			348 lines
		
	
	
	
		
			9.2 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			348 lines
		
	
	
	
		
			9.2 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
# Testing various forms of idempotency for replication.  This file is
 | 
						|
# for tests that should only be executed in row mode.
 | 
						|
 | 
						|
source include/have_binlog_format_row.inc;
 | 
						|
source include/master-slave.inc;
 | 
						|
connection master;
 | 
						|
source include/have_innodb.inc;
 | 
						|
connection slave;
 | 
						|
source include/have_innodb.inc;
 | 
						|
 | 
						|
# Add suppression for expected warning(s) in slaves error log
 | 
						|
call mtr.add_suppression("Can.t find record in .t[12].* error.* 1032");
 | 
						|
call mtr.add_suppression("Cannot delete or update a parent row: a foreign key constraint fails .* error.* 1451");
 | 
						|
call mtr.add_suppression("Cannot add or update a child row: a foreign key constraint fails .* error.* 1452");
 | 
						|
call mtr.add_suppression("Duplicate entry .1. for key .PRIMARY.* error.* 1062");
 | 
						|
call mtr.add_suppression("Can't find record in 't1'");
 | 
						|
call mtr.add_suppression("Can't find record in 't2'");
 | 
						|
 | 
						|
 | 
						|
# bug#31609 Not all RBR slave errors reported as errors
 | 
						|
# bug#31552 Replication breaks when deleting rows from out-of-sync table
 | 
						|
#           without PK
 | 
						|
 | 
						|
# The default for slave-exec-mode option and server
 | 
						|
# variable slave_exec_mode  is 'STRICT'.
 | 
						|
# When 'STRICT' mode is set, the slave SQL thread will stop whenever
 | 
						|
# the row to change is not found. In 'IDEMPOTENT' mode, the SQL thread
 | 
						|
# will continue running and apply the row - replace if it's Write_rows event -
 | 
						|
# or skip to the next event.
 | 
						|
 | 
						|
# the previous part of the tests was with IDEMPOTENT slave's mode.
 | 
						|
 | 
						|
 | 
						|
#
 | 
						|
# Other than above idempotent errors dealing with foreign keys constraint
 | 
						|
#
 | 
						|
connection slave;
 | 
						|
 | 
						|
set @old_slave_exec_mode= @@global.slave_exec_mode;
 | 
						|
set @@global.slave_exec_mode= IDEMPOTENT;
 | 
						|
 | 
						|
connection master;
 | 
						|
 | 
						|
create table ti1 (b int primary key) engine = innodb;
 | 
						|
create table ti2 (a int primary key, b int, foreign key (b) references ti1(b))
 | 
						|
     engine = innodb;
 | 
						|
set foreign_key_checks=1 /* ensure the check */;
 | 
						|
 | 
						|
insert into ti1 values (1),(2),(3);
 | 
						|
insert into ti2 set a=2, b=2;
 | 
						|
 | 
						|
sync_slave_with_master;
 | 
						|
 | 
						|
#connection slave;
 | 
						|
select * from ti1 order by b /* must be (1),(2),(3) */;
 | 
						|
insert into ti2 set a=1, b=1;
 | 
						|
select * from ti2 order by b /* must be (1,1) (2,2) */;
 | 
						|
 | 
						|
connection master;
 | 
						|
 | 
						|
# from now on checking rbr specific idempotent errors
 | 
						|
set @save_binlog_format= @@session.binlog_format;
 | 
						|
set @@session.binlog_format= row;
 | 
						|
delete from ti1 where b=1;
 | 
						|
 | 
						|
select * from ti1 order by b /* must be (2),(3) */;
 | 
						|
 | 
						|
# slave must catch up (expect some warnings in error.log)
 | 
						|
sync_slave_with_master;
 | 
						|
 | 
						|
#connection slave;
 | 
						|
select * from ti1 order by b /* must stays as were on master (1),(2),(3) */;
 | 
						|
 | 
						|
delete from ti1 where b=3;
 | 
						|
 | 
						|
connection master;
 | 
						|
insert into ti2 set a=3, b=3;
 | 
						|
 | 
						|
# slave must catch up (expect some warnings in error.log)
 | 
						|
sync_slave_with_master;
 | 
						|
 | 
						|
#connection slave;
 | 
						|
select * from ti2 order by b /* must be (1,1),(2,2) - not inserted */;
 | 
						|
 | 
						|
 | 
						|
#
 | 
						|
# Checking the new global sys variable
 | 
						|
#
 | 
						|
 | 
						|
connection slave;
 | 
						|
 | 
						|
set global slave_exec_mode='IDEMPOTENT';
 | 
						|
set global slave_exec_mode='STRICT';
 | 
						|
 | 
						|
# checking mutual exclusion for the options
 | 
						|
--error ER_WRONG_VALUE_FOR_VAR
 | 
						|
set global slave_exec_mode='IDEMPOTENT,STRICT';
 | 
						|
 | 
						|
select @@global.slave_exec_mode /* must be STRICT */;
 | 
						|
 | 
						|
#
 | 
						|
# Checking stops.
 | 
						|
# In the following sections strict slave sql thread is going to
 | 
						|
# stop when faces an idempotent error. In order to proceed
 | 
						|
# the mode is temporarily switched to idempotent.
 | 
						|
#
 | 
						|
 | 
						|
#
 | 
						|
--echo *** foreign keys errors as above now forces to stop
 | 
						|
#
 | 
						|
 | 
						|
connection master;
 | 
						|
 | 
						|
set foreign_key_checks=0;
 | 
						|
drop table ti2, ti1;
 | 
						|
 | 
						|
create table ti1 (b int primary key) engine = innodb;
 | 
						|
create table ti2 (a int primary key, b int, foreign key (b) references ti1(b))
 | 
						|
     engine = innodb;
 | 
						|
set foreign_key_checks=1 /* ensure the check */;
 | 
						|
 | 
						|
insert into ti1 values (1),(2),(3);
 | 
						|
insert into ti2 set a=2, b=2;
 | 
						|
 | 
						|
sync_slave_with_master;
 | 
						|
 | 
						|
#connection slave;
 | 
						|
select * from ti1 order by b /* must be (1),(2),(3) */;
 | 
						|
--echo *** conspire future problem
 | 
						|
insert into ti2 set a=1, b=1;
 | 
						|
select * from ti2 order by b /* must be (1,1) (2,2) */;
 | 
						|
 | 
						|
connection master;
 | 
						|
 | 
						|
delete from ti1 where b=1 /* offending delete event */;
 | 
						|
select * from ti1 order by b /* must be (2),(3) */;
 | 
						|
 | 
						|
# foreign key: row is referenced
 | 
						|
 | 
						|
--echo *** slave must stop (Trying to delete a referenced foreign key)
 | 
						|
connection slave;
 | 
						|
# ER_ROW_IS_REFERENCED_2 # Cannot add or update a child row: a foreign key constraint fails 
 | 
						|
--let slave_sql_errno= 1451
 | 
						|
source include/wait_for_slave_sql_error.inc;
 | 
						|
 | 
						|
let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1);
 | 
						|
disable_query_log;
 | 
						|
eval SELECT "$last_error" AS Last_SQL_Error;
 | 
						|
enable_query_log;
 | 
						|
 | 
						|
select * from ti1 order by b /* must be (1),(2),(3) - not deleted */;
 | 
						|
set foreign_key_checks= 0;
 | 
						|
delete from ti2 where b=1;
 | 
						|
set foreign_key_checks= 1;
 | 
						|
set global slave_exec_mode='IDEMPOTENT';
 | 
						|
start slave sql_thread;
 | 
						|
connection master;
 | 
						|
sync_slave_with_master;
 | 
						|
#connection slave;
 | 
						|
set global slave_exec_mode='STRICT';
 | 
						|
 | 
						|
connection master;
 | 
						|
 | 
						|
sync_slave_with_master;
 | 
						|
 | 
						|
#connection slave;
 | 
						|
--echo *** conspire the following insert failure
 | 
						|
# foreign key: no referenced row
 | 
						|
 | 
						|
--echo *** conspire future problem
 | 
						|
delete from ti1 where b=3;
 | 
						|
 | 
						|
connection master;
 | 
						|
insert into ti2 set a=3, b=3 /* offending write event */;
 | 
						|
 | 
						|
--echo *** slave must stop (Trying to insert an invalid foreign key)
 | 
						|
connection slave;
 | 
						|
# ER_NO_REFERENCED_ROW_2 # Cannot add or update a parent row: a foreign key constraint fails
 | 
						|
--let slave_sql_errno= 1452
 | 
						|
source include/wait_for_slave_sql_error.inc;
 | 
						|
 | 
						|
let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1);
 | 
						|
disable_query_log;
 | 
						|
eval SELECT "$last_error" AS Last_SQL_Error;
 | 
						|
enable_query_log;
 | 
						|
 | 
						|
select * from ti2 order by b /* must be (2,2) */;
 | 
						|
set foreign_key_checks= 0;
 | 
						|
insert into ti1 set b=3;
 | 
						|
set foreign_key_checks= 1;
 | 
						|
set global slave_exec_mode='IDEMPOTENT';
 | 
						|
start slave sql_thread;
 | 
						|
connection master;
 | 
						|
sync_slave_with_master;
 | 
						|
#connection slave;
 | 
						|
set global slave_exec_mode='STRICT';
 | 
						|
 | 
						|
connection master;
 | 
						|
 | 
						|
sync_slave_with_master;
 | 
						|
 | 
						|
select * from ti2 order by b /* must be (2,2),(3,3) */;
 | 
						|
 | 
						|
# 
 | 
						|
--echo *** other errors
 | 
						|
# 
 | 
						|
 | 
						|
# dup key insert
 | 
						|
 | 
						|
#connection slave;
 | 
						|
--echo *** conspiring query
 | 
						|
insert into ti1 set b=1;
 | 
						|
 | 
						|
connection master;
 | 
						|
insert into ti1 set b=1 /* offending write event */;
 | 
						|
 | 
						|
--echo *** slave must stop (Trying to insert a duplicate key)
 | 
						|
connection slave;
 | 
						|
# ER_DUP_ENTRY # Duplicate entry for key
 | 
						|
--let slave_sql_errno= 1062
 | 
						|
source include/wait_for_slave_sql_error.inc;
 | 
						|
 | 
						|
let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1);
 | 
						|
disable_query_log;
 | 
						|
eval SELECT "$last_error" AS Last_SQL_Error;
 | 
						|
enable_query_log;
 | 
						|
 | 
						|
set foreign_key_checks= 0;
 | 
						|
delete from ti1 where b=1;
 | 
						|
set foreign_key_checks= 1;
 | 
						|
set global slave_exec_mode='IDEMPOTENT';
 | 
						|
start slave sql_thread;
 | 
						|
connection master;
 | 
						|
sync_slave_with_master;
 | 
						|
#connection slave;
 | 
						|
set global slave_exec_mode='STRICT';
 | 
						|
 | 
						|
# key not found
 | 
						|
 | 
						|
connection master;
 | 
						|
 | 
						|
CREATE TABLE t1 (a INT PRIMARY KEY);
 | 
						|
CREATE TABLE t2 (a INT);
 | 
						|
INSERT INTO t1 VALUES (-1),(-2),(-3);
 | 
						|
INSERT INTO t2 VALUES (-1),(-2),(-3);
 | 
						|
sync_slave_with_master;
 | 
						|
 | 
						|
#connection slave;
 | 
						|
DELETE FROM t1 WHERE a = -2;
 | 
						|
DELETE FROM t2 WHERE a = -2;
 | 
						|
connection master;
 | 
						|
DELETE FROM t1 WHERE a = -2;
 | 
						|
 | 
						|
--echo *** slave must stop (Key was not found)
 | 
						|
connection slave;
 | 
						|
# ER_KEY_NOT_FOUND # Can't find record
 | 
						|
--let slave_sql_errno= 1032
 | 
						|
source include/wait_for_slave_sql_error.inc;
 | 
						|
 | 
						|
 | 
						|
let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1);
 | 
						|
disable_query_log;
 | 
						|
eval SELECT "$last_error" AS Last_SQL_Error;
 | 
						|
enable_query_log;
 | 
						|
 | 
						|
set global slave_exec_mode='IDEMPOTENT';
 | 
						|
start slave sql_thread;
 | 
						|
connection master;
 | 
						|
sync_slave_with_master;
 | 
						|
#connection slave;
 | 
						|
set global slave_exec_mode='STRICT';
 | 
						|
 | 
						|
connection master;
 | 
						|
DELETE FROM t2 WHERE a = -2; 
 | 
						|
--echo *** slave must stop (Key was not found)
 | 
						|
connection slave;
 | 
						|
# ER_KEY_NOT_FOUND # Can't find record
 | 
						|
--let slave_sql_errno= 1032
 | 
						|
source include/wait_for_slave_sql_error.inc;
 | 
						|
 | 
						|
let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1);
 | 
						|
disable_query_log;
 | 
						|
eval SELECT "$last_error" AS Last_SQL_Error;
 | 
						|
enable_query_log;
 | 
						|
 | 
						|
set global slave_exec_mode='IDEMPOTENT';
 | 
						|
start slave sql_thread;
 | 
						|
connection master;
 | 
						|
sync_slave_with_master;
 | 
						|
#connection slave;
 | 
						|
set global slave_exec_mode='STRICT';
 | 
						|
 | 
						|
UPDATE t1 SET a = 1 WHERE a = -1;
 | 
						|
UPDATE t2 SET a = 1 WHERE a = -1;
 | 
						|
 | 
						|
connection master;
 | 
						|
UPDATE t1 SET a = 1 WHERE a = -1;
 | 
						|
 | 
						|
--echo *** slave must stop (Key was not found)
 | 
						|
connection slave;
 | 
						|
# ER_KEY_NOT_FOUND # Can't find record
 | 
						|
--let slave_sql_errno= 1032
 | 
						|
source include/wait_for_slave_sql_error.inc;
 | 
						|
 | 
						|
let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1);
 | 
						|
disable_query_log;
 | 
						|
eval SELECT "$last_error" AS Last_SQL_Error;
 | 
						|
enable_query_log;
 | 
						|
 | 
						|
set global slave_exec_mode='IDEMPOTENT';
 | 
						|
start slave sql_thread;
 | 
						|
connection master;
 | 
						|
sync_slave_with_master;
 | 
						|
#connection slave;
 | 
						|
set global slave_exec_mode='STRICT';
 | 
						|
 | 
						|
 | 
						|
connection master;
 | 
						|
UPDATE t2 SET a = 1 WHERE a = -1;
 | 
						|
 | 
						|
--echo *** slave must stop (Key was not found)
 | 
						|
connection slave;
 | 
						|
# ER_KEY_NOT_FOUND # Can't find record
 | 
						|
--let slave_sql_errno= 1032
 | 
						|
source include/wait_for_slave_sql_error.inc;
 | 
						|
 | 
						|
let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1);
 | 
						|
disable_query_log;
 | 
						|
eval SELECT "$last_error" AS Last_SQL_Error;
 | 
						|
enable_query_log;
 | 
						|
 | 
						|
set global slave_exec_mode='IDEMPOTENT';
 | 
						|
start slave sql_thread;
 | 
						|
connection master;
 | 
						|
sync_slave_with_master;
 | 
						|
#connection slave;
 | 
						|
SET @@global.slave_exec_mode= @old_slave_exec_mode;
 | 
						|
 | 
						|
# cleanup for bug#31609 tests
 | 
						|
 | 
						|
connection master;
 | 
						|
 | 
						|
drop table t1,t2,ti2,ti1;
 | 
						|
sync_slave_with_master;
 | 
						|
set @@global.slave_exec_mode= @old_slave_exec_mode;
 | 
						|
 | 
						|
--echo *** end of tests
 | 
						|
--source include/rpl_end.inc
 |