######################################################################################## # This test does two things. First it verifies if the binlog is not corrupted when # the cache buffer is not big enough to accommodate the changes and is divided in # five steps: # # 1 - Single Statements: # 1.1 - Single statement on transactional table. # 1.2 - Single statement on non-transactional table. # 1.3 - Single statement on both transactional and non-transactional tables. # # In both 1.2 and 1.3, an incident event is logged to notify the user that the # master and slave are diverging. # # 2 - Transactions ended by an implicit commit. # # 3 - Transactions ended by a COMMIT. # # 4 - Transactions ended by a ROLLBACK. # # 5 - Transactions with a failing statement that updates a non-transactional # table. In this case, a failure means that the statement does not get into # the cache and an incident event is logged to notify the user that the master # and slave are diverging. # # Then it checks what happens when we try to set BINLOG_CACHE_SIZE to a value that # is greater than MAX_BINLOG_CACHE_SIZE and vice-versa. In both cases, We expect # that BINLOG_CACHE_SIZE will be set to MAX_BINLOG_CACHE_SIZE. (BUG#55377) ######################################################################################## --source include/have_myisam.inc call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); call mtr.add_suppression("Option binlog_cache_size "); call mtr.add_suppression("Slave SQL for channel '': The incident LOST_EVENTS occured on the master."); call mtr.add_suppression("The content of the statement cache is corrupted " "while writing a rollback record of the transaction " "to the binary log. An incident event has been " "written to the binary log which will stop the " "slaves."); call mtr.add_suppression("Error happend while resetting the transaction " "cache for a rolled back transaction or a single " "statement not inside a transaction. An incident " "event has been written to the binary log which " "will stop the slaves."); let $old_max_binlog_cache_size= query_get_value(SHOW VARIABLES LIKE "max_binlog_cache_size", Value, 1); let $old_binlog_cache_size= query_get_value(SHOW VARIABLES LIKE "binlog_cache_size", Value, 1); let $old_max_binlog_stmt_cache_size= query_get_value(SHOW VARIABLES LIKE "max_binlog_stmt_cache_size", Value, 1); let $old_binlog_stmt_cache_size= query_get_value(SHOW VARIABLES LIKE "binlog_stmt_cache_size", Value, 1); SET GLOBAL max_binlog_cache_size = 4096; SET GLOBAL binlog_cache_size = 4096; SET GLOBAL max_binlog_stmt_cache_size = 4096; SET GLOBAL binlog_stmt_cache_size = 4096; disconnect master; connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,); CREATE TABLE t1(a INT PRIMARY KEY, data VARCHAR(30000)) ENGINE=Innodb; CREATE TABLE t2(a INT PRIMARY KEY, data VARCHAR(30000)) ENGINE=MyIsam; CREATE TABLE t3(a INT PRIMARY KEY, data VARCHAR(30000)) ENGINE=Innodb; let $data = `select concat('"', repeat('a',2000), '"')`; --echo ###### 1 - SINGLE STATEMENT ###### connection master; --echo *** Single statement on transactional table *** --disable_query_log --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE eval INSERT INTO t1 (a, data) VALUES (1, CONCAT($data, $data, $data, $data, $data)); --enable_query_log --echo *** Single statement on non-transactional table *** --disable_query_log --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE eval INSERT INTO t2 (a, data) VALUES (2, CONCAT($data, $data, $data, $data, $data, $data)); --enable_query_log # Incident event # 1590=ER_SLAVE_INCIDENT --let $slave_sql_errno= 1590 --source include/wait_for_slave_sql_error_and_skip.inc --disable_query_log eval INSERT INTO t1 (a, data) VALUES (3, $data); eval INSERT INTO t1 (a, data) VALUES (4, $data); eval INSERT INTO t1 (a, data) VALUES (5, $data); eval INSERT INTO t2 (a, data) VALUES (3, $data); eval INSERT INTO t2 (a, data) VALUES (4, $data); eval INSERT INTO t2 (a, data) VALUES (5, $data); --enable_query_log --echo *** Single statement on both transactional and non-transactional tables. *** --disable_query_log --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE eval UPDATE t2, t1 SET t2.data = CONCAT($data, $data, $data, $data), t1.data = CONCAT($data, $data, $data, $data); --enable_query_log # 1590=ER_SLAVE_INCIDENT --let $slave_sql_errno= 1590 --let $slave_skip_counter= `SELECT IF(@@binlog_format = 'ROW', 2, 1)` --source include/wait_for_slave_sql_error_and_skip.inc --let $diff_tables= master:t1,slave:t1 --source include/diff_tables.inc --echo ######### 2 - BEGIN - IMPLICIT COMMIT by DDL ######### connection master; TRUNCATE TABLE t1; TRUNCATE TABLE t2; TRUNCATE TABLE t3; BEGIN; --disable_query_log --eval INSERT INTO t1 (a, data) VALUES (1, $data); --eval INSERT INTO t1 (a, data) VALUES (2, $data); --eval INSERT INTO t1 (a, data) VALUES (3, $data); --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE --eval INSERT INTO t1 (a, data) VALUES (4, $data); --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE --eval INSERT INTO t1 (a, data) VALUES (5, $data); --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE --eval INSERT INTO t1 (a, data) VALUES (6, $data); --eval INSERT INTO t1 (a, data) VALUES (7, 's'); --eval INSERT INTO t2 (a, data) VALUES (8, 's'); --eval INSERT INTO t1 (a, data) VALUES (9, 's'); --enable_query_log --disable_query_log ALTER TABLE t3 ADD COLUMN d int; --enable_query_log --disable_query_log --eval INSERT INTO t2 (a, data) VALUES (10, $data); --eval INSERT INTO t2 (a, data) VALUES (11, $data); --eval INSERT INTO t2 (a, data) VALUES (12, $data); --eval INSERT INTO t2 (a, data) VALUES (13, $data); --enable_query_log BEGIN; --disable_query_log --eval INSERT INTO t1 (a, data) VALUES (14, $data); --eval INSERT INTO t1 (a, data) VALUES (15, $data); --eval INSERT INTO t1 (a, data) VALUES (16, $data); --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE --eval INSERT INTO t1 (a, data) VALUES (17, $data); --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE --eval INSERT INTO t1 (a, data) VALUES (18, $data); --eval INSERT INTO t1 (a, data) VALUES (19, 's'); --eval INSERT INTO t2 (a, data) VALUES (20, 's'); --eval INSERT INTO t1 (a, data) VALUES (21, 's'); --enable_query_log if (`SELECT @@binlog_format = 'STATEMENT' || @@binlog_format = 'MIXED'`) { --disable_query_log CREATE TABLE t4 SELECT * FROM t1; --enable_query_log } if (`SELECT @@binlog_format = 'ROW'`) { --disable_query_log --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE CREATE TABLE t4 SELECT * FROM t1; --enable_query_log } --disable_query_log --eval INSERT INTO t2 (a, data) VALUES (15, $data); --enable_query_log BEGIN; --disable_query_log --eval INSERT INTO t1 (a, data) VALUES (22, $data); --eval INSERT INTO t1 (a, data) VALUES (23, $data); --eval INSERT INTO t1 (a, data) VALUES (24, $data); --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE --eval INSERT INTO t1 (a, data) VALUES (25, $data); --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE --eval INSERT INTO t1 (a, data) VALUES (26, $data); --eval INSERT INTO t1 (a, data) VALUES (27, 's'); --eval INSERT INTO t2 (a, data) VALUES (28, 's'); --eval INSERT INTO t1 (a, data) VALUES (29, 's'); --enable_query_log --disable_query_log CREATE TABLE t5 (a int); --enable_query_log --sync_slave_with_master --let $diff_tables= master:t1,slave:t1 --source include/diff_tables.inc --echo ###### 3 - BEGIN - COMMIT ###### connection master; TRUNCATE TABLE t1; TRUNCATE TABLE t2; TRUNCATE TABLE t3; BEGIN; --disable_query_log --eval INSERT INTO t1 (a, data) VALUES (1, $data); --eval INSERT INTO t1 (a, data) VALUES (2, $data); --eval INSERT INTO t1 (a, data) VALUES (3, $data); --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE --eval INSERT INTO t1 (a, data) VALUES (4, $data); --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE --eval INSERT INTO t1 (a, data) VALUES (5, $data); --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE --eval INSERT INTO t1 (a, data) VALUES (6, $data); --eval INSERT INTO t1 (a, data) VALUES (7, 's'); --eval INSERT INTO t2 (a, data) VALUES (8, 's'); --eval INSERT INTO t1 (a, data) VALUES (9, 's'); --enable_query_log COMMIT; --sync_slave_with_master --let $diff_tables= master:t1,slave:t1 --source include/diff_tables.inc --echo ####### 4 - BEGIN - ROLLBACK ####### connection master; TRUNCATE TABLE t1; TRUNCATE TABLE t2; TRUNCATE TABLE t3; BEGIN; --disable_query_log --eval INSERT INTO t1 (a, data) VALUES (1, $data); --eval INSERT INTO t1 (a, data) VALUES (2, $data); --eval INSERT INTO t1 (a, data) VALUES (3, $data); --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE --eval INSERT INTO t1 (a, data) VALUES (4, $data); --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE --eval INSERT INTO t1 (a, data) VALUES (5, $data); --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE --eval INSERT INTO t1 (a, data) VALUES (6, $data); --eval INSERT INTO t1 (a, data) VALUES (7, 's'); --eval INSERT INTO t2 (a, data) VALUES (8, 's'); --eval INSERT INTO t1 (a, data) VALUES (9, 's'); --enable_query_log ROLLBACK; --sync_slave_with_master --let $diff_tables= master:t1,slave:t1 --source include/diff_tables.inc --echo ###### 5 - PROCEDURE ####### connection master; TRUNCATE TABLE t1; TRUNCATE TABLE t2; TRUNCATE TABLE t3; DELIMITER //; CREATE PROCEDURE p1(pd VARCHAR(30000)) BEGIN INSERT INTO t1 (a, data) VALUES (1, pd); INSERT INTO t1 (a, data) VALUES (2, pd); INSERT INTO t1 (a, data) VALUES (3, pd); INSERT INTO t1 (a, data) VALUES (4, pd); INSERT INTO t1 (a, data) VALUES (5, 's'); END// DELIMITER ;// TRUNCATE TABLE t1; --disable_query_log eval CALL p1($data); --enable_query_log TRUNCATE TABLE t1; BEGIN; --disable_query_log --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE eval CALL p1($data); --enable_query_log COMMIT; TRUNCATE TABLE t1; BEGIN; --disable_query_log --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE eval CALL p1($data); --enable_query_log ROLLBACK; --sync_slave_with_master --let $diff_tables= master:t1,slave:t1 --source include/diff_tables.inc --echo ####### 6 - XID ###### connection master; TRUNCATE TABLE t1; TRUNCATE TABLE t2; TRUNCATE TABLE t3; BEGIN; --disable_query_log --eval INSERT INTO t1 (a, data) VALUES (1, $data); --eval INSERT INTO t1 (a, data) VALUES (2, $data); --eval INSERT INTO t1 (a, data) VALUES (3, $data); --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE --eval INSERT INTO t1 (a, data) VALUES (4, $data); SAVEPOINT sv; --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE --eval INSERT INTO t1 (a, data) VALUES (5, $data); --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE --eval INSERT INTO t1 (a, data) VALUES (6, $data); --eval INSERT INTO t1 (a, data) VALUES (7, 's'); --eval INSERT INTO t2 (a, data) VALUES (8, 's'); --eval INSERT INTO t1 (a, data) VALUES (9, 's'); --enable_query_log ROLLBACK TO sv; COMMIT; --sync_slave_with_master --let $diff_tables= master:t1,slave:t1 --source include/diff_tables.inc --echo ####### 7 - NON-TRANS TABLE ####### connection master; TRUNCATE TABLE t1; TRUNCATE TABLE t2; TRUNCATE TABLE t3; BEGIN; --disable_query_log --eval INSERT INTO t1 (a, data) VALUES (1, $data); --eval INSERT INTO t1 (a, data) VALUES (2, $data); --eval INSERT INTO t2 (a, data) VALUES (3, $data); --eval INSERT INTO t1 (a, data) VALUES (4, $data); --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE --eval INSERT INTO t1 (a, data) VALUES (5, $data); --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE --eval INSERT INTO t1 (a, data) VALUES (6, $data); --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE --eval INSERT INTO t1 (a, data) VALUES (7, $data); --eval UPDATE t2 SET data= CONCAT($data, $data); --eval INSERT INTO t1 (a, data) VALUES (8, 's'); --eval INSERT INTO t1 (a, data) VALUES (9, 's'); --eval INSERT INTO t2 (a, data) VALUES (10, 's'); --eval INSERT INTO t1 (a, data) VALUES (11, 's'); --enable_query_log COMMIT; BEGIN; --disable_query_log --eval INSERT INTO t1 (a, data) VALUES (15, $data); --eval INSERT INTO t1 (a, data) VALUES (16, $data); --eval INSERT INTO t2 (a, data) VALUES (17, $data); --eval INSERT INTO t1 (a, data) VALUES (18, $data); --error ER_TRANS_CACHE_FULL, ER_STMT_CACHE_FULL, ER_ERROR_ON_WRITE --eval INSERT INTO t1 (a, data) VALUES (19, $data); --enable_query_log COMMIT; --sync_slave_with_master --let $diff_tables= master:t1,slave:t1 --source include/diff_tables.inc --echo ####### 8 - LOAD DATA INFILE INTO TABLE ####### # # This scenario verifies that load data infile fails when # binlog cache exceeds max_binlog_cache_size # --source include/rpl_connection_master.inc CREATE TABLE t6 (a varchar(20)) ENGINE=Innodb; # Save the current binary log position --let $pos_before= query_get_value(show master status,Position,1) --disable_query_log --let $write_var =`SELECT REPEAT('Testing\n', 1000)` --let $write_to_file = GENERATE --source include/write_var_to_file.inc --enable_query_log # Below transaction generates transaction cache more than # the max_binlog_cache_size i.e 4096. Hence results in error. --replace_result $write_to_file temp_file --error ER_TRANS_CACHE_FULL eval LOAD DATA INFILE '$write_to_file' INTO TABLE t6; --exec rm $write_to_file # Check that the above transaction has not been logged in the binary log --let $assert_text= assert that the above Event has not been added to binlog --let $assert_cond= [SHOW MASTER STATUS, Position,1] = $pos_before --source include/assert.inc # Check that the table is empty on master --let $assert_text = Check that the LOAD DATA didn't add any data into the table --let $assert_cond = [SELECT COUNT(*) FROM t6] = 0 --source include/assert.inc --source include/sync_slave_sql_with_master.inc # Check that the table is empty on slave --let $assert_text = Check that the LOAD DATA didn't add any data into the table --let $assert_cond = [SELECT COUNT(*) FROM t6] = 0 --source include/assert.inc --source include/rpl_connection_master.inc DROP TABLE t6; --source include/sync_slave_sql_with_master.inc --echo ######### 9 - Bug#55375(Regression Bug) Transaction bigger than ########## --echo ######### max_binlog_cache_size crashes slave ########## --echo # [ On Slave ] SET GLOBAL max_binlog_cache_size = 4096; SET GLOBAL binlog_cache_size = 4096; SET GLOBAL max_binlog_stmt_cache_size = 4096; SET GLOBAL binlog_stmt_cache_size = 4096; source include/stop_slave.inc; source include/start_slave.inc; CALL mtr.add_suppression("Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage.*"); CALL mtr.add_suppression("Multi-statement transaction required more than 'max_binlog_stmt_cache_size' bytes of storage.*"); CALL mtr.add_suppression("Writing one row to the row-based binary log failed.*"); CALL mtr.add_suppression("Slave SQL.*The incident LOST_EVENTS occured on the master. Message: error writing to the binary log"); call mtr.add_suppression("The slave coordinator and worker threads are stopped, possibly leaving data in inconsistent state"); connection master; TRUNCATE t1; sync_slave_with_master; --let binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1) --let binlog_file= query_get_value(SHOW MASTER STATUS, File, 1) connection master; --replace_result $old_max_binlog_cache_size ORIGINAL_VALUE --eval SET GLOBAL max_binlog_cache_size= $old_max_binlog_cache_size --replace_result $old_binlog_cache_size ORIGINAL_VALUE --eval SET GLOBAL binlog_cache_size= $old_binlog_cache_size --replace_result $old_max_binlog_stmt_cache_size ORIGINAL_VALUE --eval SET GLOBAL max_binlog_stmt_cache_size= $old_max_binlog_stmt_cache_size --replace_result $old_binlog_stmt_cache_size ORIGINAL_VALUE --eval SET GLOBAL binlog_stmt_cache_size= $old_binlog_stmt_cache_size disconnect master; connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,); --let $n=128 BEGIN; --disable_query_log --echo Repeat statement 'INSERT INTO t1 VALUES(\$n, repeat("a", 32))' $n times while ($n) { --eval INSERT INTO t1 VALUES ($n, repeat("a", 32)) --dec $n } --enable_query_log COMMIT; --connection slave --let $slave_sql_errno= 1534,1197 source include/wait_for_slave_sql_error.inc; SELECT count(*) FROM t1; source include/show_binlog_events.inc; --replace_result $old_max_binlog_cache_size ORIGINAL_VALUE --eval SET GLOBAL max_binlog_cache_size= $old_max_binlog_cache_size --replace_result $old_binlog_cache_size ORIGINAL_VALUE --eval SET GLOBAL binlog_cache_size= $old_binlog_cache_size --replace_result $old_max_binlog_stmt_cache_size ORIGINAL_VALUE --eval SET GLOBAL max_binlog_stmt_cache_size= $old_max_binlog_stmt_cache_size --replace_result $old_binlog_stmt_cache_size ORIGINAL_VALUE --eval SET GLOBAL binlog_stmt_cache_size= $old_binlog_stmt_cache_size source include/stop_slave.inc; source include/start_slave.inc; connection master; sync_slave_with_master; SELECT count(*) FROM t1; --echo ######## CHECK MAX_BINLOG_CACHE_SIZE and BINLOG_CACHE_SIZE ######### # # Checking what happens when we try to set BINLOG_CACHE_SIZE to a value that is # greater than MAX_BINLOG_CACHE_SIZE and vice-versa. In both cases, We expect # that BINLOG_CACHE_SIZE will be set to MAX_BINLOG_CACHE_SIZE. (BUG#55377) # connection master; SET @@GLOBAL.MAX_BINLOG_CACHE_SIZE= 8192; SHOW VARIABLES LIKE 'MAX_BINLOG_CACHE_SIZE'; SHOW VARIABLES LIKE 'BINLOG_CACHE_SIZE'; SET @@GLOBAL.BINLOG_CACHE_SIZE= 16384; SHOW VARIABLES LIKE 'MAX_BINLOG_CACHE_SIZE'; SHOW VARIABLES LIKE 'BINLOG_CACHE_SIZE'; SET @@GLOBAL.MAX_BINLOG_CACHE_SIZE= 4096; SHOW VARIABLES LIKE 'MAX_BINLOG_CACHE_SIZE'; SHOW VARIABLES LIKE 'BINLOG_CACHE_SIZE'; --echo ######### CLEAN ######### --disable_query_log --eval SET GLOBAL max_binlog_cache_size= $old_max_binlog_cache_size --eval SET GLOBAL binlog_cache_size= $old_binlog_cache_size --enable_query_log DROP TABLE t1; DROP TABLE t2; DROP TABLE t3; # t4 exists only if binlog_format!=row, so so a warning is generated # if binog_format=row --disable_warnings DROP TABLE IF EXISTS t4; --enable_warnings DROP TABLE t5; DROP PROCEDURE p1;