diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:00:34 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:00:34 +0000 |
commit | 3f619478f796eddbba6e39502fe941b285dd97b1 (patch) | |
tree | e2c7b5777f728320e5b5542b6213fd3591ba51e2 /mysql-test/suite/binlog/t | |
parent | Initial commit. (diff) | |
download | mariadb-upstream.tar.xz mariadb-upstream.zip |
Adding upstream version 1:10.11.6.upstream/1%10.11.6upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mysql-test/suite/binlog/t')
179 files changed, 11914 insertions, 0 deletions
diff --git a/mysql-test/suite/binlog/t/backup.test b/mysql-test/suite/binlog/t/backup.test new file mode 100644 index 00000000..e1d921c7 --- /dev/null +++ b/mysql-test/suite/binlog/t/backup.test @@ -0,0 +1,19 @@ +--source include/have_log_bin.inc +--source include/have_binlog_format_mixed.inc + +--echo # +--echo # Test BACKUP STAGES BLOCK_COMMIT with binary logging on +--echo # + +SET BINLOG_FORMAT=MIXED; +RESET MASTER; + +create table t1 (a int) engine=aria; +insert into t1 values (1); + +BACKUP STAGE START; +BACKUP STAGE BLOCK_COMMIT; +SELECT @@gtid_binlog_pos; +BACKUP STAGE END; +source include/show_binlog_events.inc; +drop table t1; diff --git a/mysql-test/suite/binlog/t/binlog_1pc.test b/mysql-test/suite/binlog/t/binlog_1pc.test new file mode 100644 index 00000000..8465ff17 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_1pc.test @@ -0,0 +1,39 @@ +# The test file contains tests specific to one phase commit +# execution and binlogging. +# +# MDEV-26031 unnessary xid logging in one phase commit case +# +--source include/have_innodb.inc +--source include/have_aria.inc +--source include/have_binlog_format_mixed.inc + +RESET MASTER; + +CREATE TABLE t (f INT) ENGINE=INNODB; +CREATE TABLE ta (f INT) ENGINE=Aria; + +--let $binlog_start = query_get_value(SHOW MASTER STATUS, Position, 1) +BEGIN; + INSERT INTO t SET f = 1; + INSERT INTO ta SET f = 1; +COMMIT; +--let $binlog_file = query_get_value(SHOW MASTER STATUS, File, 1) +--source include/show_binlog_events.inc + +--echo # Prove that binlog is resettable. Under the bug condition it was not. +RESET MASTER; + +--let $binlog_start = query_get_value(SHOW MASTER STATUS, Position, 1) +--let $binlog_file = query_get_value(SHOW MASTER STATUS, File, 1) +SET @@binlog_format = ROW; +CREATE TABLE ta2 ENGINE = Aria SELECT * from t; +--source include/show_binlog_events.inc + +--echo # Prove that binlog is resettable. Under the bug condition it was not. +RESET MASTER; + + +--echo # Cleanup +DROP TABLE ta2, ta, t; + +--echo # End of the tests diff --git a/mysql-test/suite/binlog/t/binlog_admin_cmd_kill.test b/mysql-test/suite/binlog/t/binlog_admin_cmd_kill.test new file mode 100644 index 00000000..e2397f0e --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_admin_cmd_kill.test @@ -0,0 +1,98 @@ +# ==== Purpose ==== +# +# Test verifies that when an admin command execution is interrupted by KILL +# command it should stop its execution. The admin command in binary log should +# contain only the list of tables which have successfully executed admin +# command prior to kill. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Create two table t1,t2. +# 1 - Execute OPTIMIZE TABLE t1,t2 command. +# 2 - Using debug sync mechanism kill OPTIMIZE TABLE command at a stage +# where it has not optimized any table. +# 3 - Check that OPTIMIZE TABLE command is not written to binary log. +# 4 - Using debug sync mechanism hold the execution of OPTIMIZE TABLE after +# t1 table optimization. Now kill the OPTIMIZE TABLE command. +# 5 - Observe the binlog output, the OPTIMIZE TABLE command should display `t1,t2`. +# 6 - Please note that, we binlog the entire query even if at least one +# table is modified as admin commands are safe to replicate and they will +# not make the slave to diverge. +# +# ==== References ==== +# +# MDEV-22530: Aborting OPTIMIZE TABLE still logs in binary log and replicates to the Slave server. +# +--source include/have_log_bin.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/have_innodb.inc + +--echo # +--echo # Kill OPTIMIZE command prior to table modification +--echo # +RESET MASTER; + +CREATE TABLE t1 (f INT) ENGINE=INNODB; +CREATE TABLE t2 (f INT) ENGINE=INNODB; + +--connect(con1,127.0.0.1,root,,test,$MASTER_MYPORT,) +--connection con1 +SET debug_sync='admin_command_kill_before_modify SIGNAL ready_to_be_killed WAIT_FOR master_cont'; +--send OPTIMIZE TABLE t1,t2 + +--connection default +SET debug_sync='now WAIT_FOR ready_to_be_killed'; +--let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%OPTIMIZE TABLE %'` + +# Now kill. +--replace_result $thd_id THD_ID +eval KILL $thd_id; + +SET debug_sync = 'reset'; +--disconnect con1 + +--source include/show_binlog_events.inc +DROP TABLE t1,t2; + +RESET MASTER; + +--echo # +--echo # Kill OPTIMIZE command after table modification +--echo # + +CREATE TABLE t1 (f INT) ENGINE=INNODB; +CREATE TABLE t2 (f INT) ENGINE=INNODB; + +--connect(con1,127.0.0.1,root,,test,$MASTER_MYPORT,) +--connection con1 +SET debug_sync='admin_command_kill_after_modify SIGNAL ready_to_be_killed WAIT_FOR master_cont'; +--send OPTIMIZE TABLE t1,t2 + +--connection default +SET debug_sync='now WAIT_FOR ready_to_be_killed'; +--let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%OPTIMIZE TABLE %'` + +# Now kill. +--replace_result $thd_id THD_ID +eval KILL $thd_id; + +SET debug_sync = 'reset'; +--disconnect con1 + +--let $wait_binlog_event= OPTIMIZE +--source include/wait_for_binlog_event.inc + +DROP TABLE t1,t2; +let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1); +FLUSH LOGS; + +--let $MYSQLD_DATADIR= `select @@datadir` +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/$binlog_file > $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out + +--let SEARCH_PATTERN= OPTIMIZE TABLE t1,t2 +--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out +--source include/search_pattern_in_file.inc + +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out diff --git a/mysql-test/suite/binlog/t/binlog_autocommit_off_no_hang-master.opt b/mysql-test/suite/binlog/t/binlog_autocommit_off_no_hang-master.opt new file mode 100644 index 00000000..e0fa81e6 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_autocommit_off_no_hang-master.opt @@ -0,0 +1 @@ +--autocommit=0 diff --git a/mysql-test/suite/binlog/t/binlog_autocommit_off_no_hang.test b/mysql-test/suite/binlog/t/binlog_autocommit_off_no_hang.test new file mode 100644 index 00000000..8f1dbb2a --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_autocommit_off_no_hang.test @@ -0,0 +1,45 @@ +# +# Purpose: +# When the mysql.gtid_slave_pos table uses the InnoDB engine, and mysqld +# starts, it reads the table and begins a transaction. After mysqld reads the +# value, it should end the transaction and release all associated locks. +# The bug reported in DBAAS-7828 shows that when autocommit is off, the locks +# are not released, resulting in indefinite hangs on future attempts to change +# gtid_slave_pos. This test ensures its fix such that the locks are properly +# released. +# +# References: +# DBAAS-7828: Primary/replica: configuration change of "autocommit=0" can +# not be applied +# + +--source include/have_innodb.inc +--source include/have_log_bin.inc + +# Reading gtid_slave_pos table is format independent so just use one for +# reduced test time +--source include/have_binlog_format_row.inc + +--let old_slave_pos_engine= query_get_value(SHOW TABLE STATUS FROM mysql LIKE 'gtid_slave_pos', Engine, 1) + +# Use a transactional engine +ALTER TABLE mysql.gtid_slave_pos ENGINE=innodb; + +--echo # Restart the server so mysqld reads the gtid_slave_pos using innodb +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--shutdown_server +--source include/wait_until_disconnected.inc +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--enable_reconnect +--source include/wait_until_connected_again.inc + +--echo # Set gtid_slave_pos should not hang +SET GLOBAL gtid_slave_pos=@@gtid_binlog_pos; +COMMIT; + +# Revert table type +--disable_query_log +--eval ALTER TABLE mysql.gtid_slave_pos ENGINE=$old_slave_pos_engine +--enable_query_log + +RESET MASTER; diff --git a/mysql-test/suite/binlog/t/binlog_base64_flag.test b/mysql-test/suite/binlog/t/binlog_base64_flag.test new file mode 100644 index 00000000..5311da54 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_base64_flag.test @@ -0,0 +1,190 @@ +# This test case verifies that the mysqlbinlog --base64-output=X flags +# work as expected, and that BINLOG statements with row events fail if +# they are not preceded by BINLOG statements with Format description +# events. +# +# See also BUG#32407. + + +# BINLOG statement does not work in embedded mode. +source include/not_embedded.inc; + +call mtr.add_suppression("BINLOG_BASE64_EVENT: According to the master's version"); +call mtr.add_suppression("BINLOG_BASE64_EVENT: Column 1 of table 'test.char128_utf8' cannot be converted"); + +disable_warnings; +DROP TABLE IF EXISTS t1; +enable_warnings; +# Test to show BUG#32407. This reads a binlog created with the +# mysql-5.1-telco-6.1 tree, specifically at the tag +# mysql-5.1.15-ndb-6.1.23, and applies it to the database. The test +# should fail before BUG#32407 was fixed and succeed afterwards. +--echo ==== Test BUG#32407 ==== + +# The binlog contains row events equivalent to: +# CREATE TABLE t1 (a int) engine = myisam +# INSERT INTO t1 VALUES (1), (1) +exec $MYSQL_BINLOG suite/binlog/std_data/bug32407.001 | $MYSQL; +# The above line should succeed and t1 should contain two ones +select * from t1; + + +# Test that a BINLOG statement encoding a row event fails unless a +# Format_description_event as been supplied with an earlier BINLOG +# statement. +--echo ==== Test BINLOG statement w/o FD event ==== + +# This is a binlog statement consisting of one Table_map_log_event and +# one Write_rows_log_event. Together, they correspond to the +# following query: +# INSERT INTO TABLE test.t1 VALUES (2) + +error ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT; +BINLOG ' +SVtYRxMBAAAAKQAAADQBAAAAABAAAAAAAAAABHRlc3QAAnQxAAEDAAE= +SVtYRxcBAAAAIgAAAFYBAAAQABAAAAAAAAEAAf/+AgAAAA== +'; +# The above line should fail and 2 should not be in the table +select * from t1; + + +# Test that it works to read a Format_description_log_event with a +# BINLOG statement, followed by a row-event in base64 from the same +# version. +--echo ==== Test BINLOG statement with FD event ==== + +# This is a binlog statement containing a Format_description_log_event +# from the same version as the Table_map and Write_rows_log_event. +BINLOG ' +ODdYRw8BAAAAZgAAAGoAAAABAAQANS4xLjIzLXJjLWRlYnVnLWxvZwAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAA4N1hHEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC +'; + +# This is a Table_map_log_event+Write_rows_log_event corresponding to: +# INSERT INTO TABLE test.t1 VALUES (3) +BINLOG ' +TFtYRxMBAAAAKQAAAH8BAAAAABAAAAAAAAAABHRlc3QAAnQxAAEDAAE= +TFtYRxcBAAAAIgAAAKEBAAAQABAAAAAAAAEAAf/+AwAAAA== +'; +# The above line should succeed and 3 should be in the table +select * from t1; + +# The same as above with one-fragment BINLOG to prove +# equivalency with the fragmented BINLOG @frag_0, @frag_1. +DELETE FROM t1 WHERE a=3; +# This is a binlog statement containing a Format_description_log_event +# from the same version as the Table_map and Write_rows_log_event. +BINLOG ' +ODdYRw8BAAAAZgAAAGoAAAABAAQANS4xLjIzLXJjLWRlYnVnLWxvZwAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAA4N1hHEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC +'; + +# This is a Table_map_log_event+Write_rows_log_event corresponding to: +# INSERT INTO TABLE test.t1 VALUES (3) +SET @binlog_fragment_0=' +TFtYRxMBAAAAKQAAAH8BAAAAABAAAAAAAAAABHRlc3QAAnQxAAEDAAE= +TFtYRxcBAAAAIgAAAKEBAAAQABAAAAAAAAEAAf/+AwAAAA== +'; +SET @binlog_fragment_1=''; +BINLOG @binlog_fragment_0, @binlog_fragment_1; +# The above line should succeed and 3 should be in the table: +select * from t1; +# show "one-shot" feature of binlog_fragment variables +SELECT @binlog_fragment_0, @binlog_fragment_1 as 'NULL','NULL'; + +# New mysqlbinlog supports --base64-output=never +--echo ==== Test --base64-output=never on a binlog with row events ==== + +# mysqlbinlog should fail +--replace_regex /#[0-9][0-9][0-9][0-9][0-9][0-9] \N*/<#>/ /SET \@\@session.pseudo_thread_id.*/<#>/ +exec $MYSQL_BINLOG --base64-output=never --print-row-count=0 --print-row-event-positions=0 suite/binlog/std_data/bug32407.001; + + +# Test that the following fails cleanly: "First, read a +# Format_description event which has N event types. Then, read an +# event of type M>N" +--echo ==== Test non-matching FD event and Row event ==== + +# This is the Format_description_log_event from +# bug32407.001, encoded in base64. It contains only the old +# row events (number of event types is 22) +BINLOG ' +4CdYRw8BAAAAYgAAAGYAAAAAAAQANS4xLjE1LW5kYi02LjEuMjQtZGVidWctbG9nAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAADgJ1hHEzgNAAgAEgAEBAQEEgAATwAEGggICAg= +'; + +# The following is a Write_rows_log_event with event type 23, i.e., +# not supported by the Format_description_log_event above. It +# corresponds to the following query: +# INSERT INTO t1 VALUES (5) +error 1149; +BINLOG ' +Dl1YRxMBAAAAKQAAADQBAAAAABAAAAAAAAAABHRlc3QAAnQxAAEDAAE= +Dl1YRxcBAAAAIgAAAFYBAAAQABAAAAAAAAEAAf/+BQAAAA== +'; +# the above line should fail and 5 should not be in the binlog. +select * from t1; + +# Test that BUG#37426 is triggered. + +CREATE TABLE char128_utf8 ( + i1 INT NOT NULL, + c CHAR(128) CHARACTER SET utf8 NOT NULL, + i2 INT NOT NULL); +CREATE TABLE char63_utf8 ( + i1 INT NOT NULL, + c CHAR(63) CHARACTER SET utf8 NOT NULL, + i2 INT NOT NULL); + +# +# This is the format description log event +# + +BINLOG ' +MuNkSA8BAAAAZgAAAGoAAAAAAAQANS4xLjI1LXJjLWRlYnVnLWxvZwAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAy42RIEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC +'; + +# ... this event corresponding to +# +# INSERT INTO char63_utf8 VALUES ( 1, "123", 1 ) +# +# The binlog event below shall not trigger the bug check + +BINLOG ' +3u9kSBMBAAAANgAAAJYBAAAAABAAAAAAAAAABHRlc3QAC2NoYXI2M191dGY4AAMD/gMC/r0A +3u9kSBcBAAAAKgAAAMABAAAQABAAAAAAAAEAA//4AQAAAAMxMjMBAAAA +'; +SELECT * FROM char63_utf8; + +# ... and this is an event corresponding to +# +# INSERT INTO char128_utf8 VALUES ( 1, "123", 1 ) +# +# The binlog event below shall trigger the bug check and produce an error +# + +error ER_UNKNOWN_ERROR; +BINLOG ' +iONkSBMBAAAANwAAAJkBAAAAABAAAAAAAAAABHRlc3QADGNoYXIxMjhfdXRmOAADA/4DAv6AAA== +iONkSBcBAAAAKwAAAMQBAAAQABAAAAAAAAEAA//4AQAAAAMAMTIzAQAAAA== +'; + +drop table t1, char63_utf8, char128_utf8; + +call mtr.add_suppression("Slave SQL.*master suffers from this bug: http:..bugs.mysql.com.bug.php.id=37426.* error.* 1105"); +call mtr.add_suppression("Slave SQL.*Table definition on master and slave does not match: Column 1 size mismatch.* error.* 1535"); +call mtr.add_suppression("Slave SQL.*Column 1 of table .test.char128_utf8. cannot be converted.* error.* 1677"); + +--echo # +--echo # Bug #54393: crash and/or valgrind errors in +--echo # mysql_client_binlog_statement +--echo # +--error ER_SYNTAX_ERROR +BINLOG ''; +--error ER_BASE64_DECODE_ERROR +BINLOG '123'; +--error ER_BASE64_DECODE_ERROR +BINLOG '-2079193929'; +--error ER_BASE64_DECODE_ERROR +BINLOG 'xç↓%~∙D╒ƒ╡'; diff --git a/mysql-test/suite/binlog/t/binlog_bug23533.test b/mysql-test/suite/binlog/t/binlog_bug23533.test new file mode 100644 index 00000000..a7749711 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_bug23533.test @@ -0,0 +1,50 @@ +############################################################# +# Bug#23533: CREATE SELECT max_binlog_cache_size test +# case needed +############################################################# + +--source include/have_innodb.inc +--source include/have_log_bin.inc +--source include/have_binlog_format_row.inc +call mtr.add_suppression("Write to binary log failed: Multi-statement transaction required more than .max_binlog_cache_size.*"); +SET AUTOCOMMIT=0; + +# Create 1st table +CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT, b TEXT, PRIMARY KEY(a)) ENGINE=InnoDB; +--disable_query_log +let $i= 1000; +while ($i) +{ + BEGIN; + eval INSERT INTO t1 VALUES($i, REPEAT('x', 4096)); + COMMIT; + dec $i; +} +--enable_query_log +SELECT COUNT(*) FROM t1; + +# Set small value for max_binlog_cache_size +let $saved_binlog_cache_size= query_get_value(SELECT @@binlog_cache_size AS Value, Value, 1); +let $saved_max_binlog_cache_size= query_get_value(SELECT @@max_binlog_cache_size AS Value, Value, 1); +SET GLOBAL binlog_cache_size=4096; +SET GLOBAL max_binlog_cache_size=4096; + +# New value of max_binlog_cache_size will apply to new session +disconnect default; +connect(default,localhost,root,,test); + +# Copied data from t1 into t2 large than max_binlog_cache_size +START TRANSACTION; +--error ER_TRANS_CACHE_FULL +CREATE TABLE t2 SELECT * FROM t1; +COMMIT; +SHOW TABLES LIKE 't%'; + +# 5.1 End of Test +--disable_query_log +eval SET GLOBAL max_binlog_cache_size=$saved_max_binlog_cache_size; +eval SET GLOBAL binlog_cache_size=$saved_binlog_cache_size; +--enable_query_log +DROP TABLE t1; +disconnect default; +connect(default,localhost,root,,test); diff --git a/mysql-test/suite/binlog/t/binlog_bug36391-master.opt b/mysql-test/suite/binlog/t/binlog_bug36391-master.opt new file mode 100644 index 00000000..56273241 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_bug36391-master.opt @@ -0,0 +1 @@ +--sql_mode=NO_BACKSLASH_ESCAPES diff --git a/mysql-test/suite/binlog/t/binlog_bug36391.test b/mysql-test/suite/binlog/t/binlog_bug36391.test new file mode 100644 index 00000000..64d91dfa --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_bug36391.test @@ -0,0 +1,30 @@ +# +# BUG#36391 and BUG#38731 +# +# The fix for BUG#20103 "Escaping with backslash does not work as expected" +# was implemented too greedy though in that it not only changes the behavior +# of backslashes within strings but in general, so disabling command shortcuts +# like \G or \C (which in turn leads to BUG#36391: "mysqlbinlog creates invalid charset statements". +# +# The test executes simple commands that are stored in the binary log and +# re-execute them through the mysql client which should have to process +# some command shortcuts. The backslashes within strings is disabled in the file +# rpl_bug36391-master.opt by the option --sql_mode=NO_BACKSLASH_ESCAPES. +# +# + +--source include/have_log_bin.inc +--source include/have_binlog_format_mixed.inc + +CREATE TABLE t1(id INT); +let $binlog= query_get_value(SHOW MASTER STATUS, File, 1); +let $binlog_path= `SELECT CONCAT(@@DATADIR, '$binlog')`; +SHOW TABLES; +FLUSH LOGS; +DROP TABLE t1; + +--exec $MYSQL_BINLOG $binlog_path | $MYSQL test +SHOW TABLES; + +# Clean up +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/binlog_checkpoint.test b/mysql-test/suite/binlog/t/binlog_checkpoint.test new file mode 100644 index 00000000..4237f33c --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_checkpoint.test @@ -0,0 +1,236 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/have_binlog_format_row.inc + +SET @old_max_binlog_size= @@global.max_binlog_size; +SET GLOBAL max_binlog_size= 4096; +SET @old_innodb_flush_log_at_trx_commit= @@global.innodb_flush_log_at_trx_commit; +SET GLOBAL innodb_flush_log_at_trx_commit= 1; +RESET MASTER; + +CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb; +CREATE TABLE t2 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Myisam; + +--echo *** Test that RESET MASTER waits for pending commit checkpoints to complete. + +# con1 will hang before doing commit checkpoint, blocking RESET MASTER. +connect(con1,localhost,root,,); +SET DEBUG_SYNC= "commit_after_group_release_commit_ordered SIGNAL con1_ready WAIT_FOR con1_go"; +send INSERT INTO t1 VALUES (1, REPEAT("x", 4100)); + +connection default; +SET DEBUG_SYNC= "now WAIT_FOR con1_ready"; +# Let's add a few binlog rotations just for good measure. +INSERT INTO t2 VALUES (1, REPEAT("x", 4100)); +INSERT INTO t2 VALUES (2, REPEAT("x", 4100)); +--source include/show_binary_logs.inc +--let $binlog_file= master-bin.000004 +--let $binlog_start= 4 +--source include/show_binlog_events.inc +SET DEBUG_SYNC= "execute_command_after_close_tables SIGNAL reset_master_done"; +send RESET MASTER; + +connect(con2,localhost,root,,); +--echo This will timeout, as RESET MASTER is blocked +SET DEBUG_SYNC= "now WAIT_FOR reset_master_done TIMEOUT 1"; +# Wake up transaction to allow RESET MASTER to complete. +SET DEBUG_SYNC= "now SIGNAL con1_go"; + +connection con1; +reap; + +connection default; +reap; +--source include/show_binary_logs.inc +--let $binlog_file= master-bin.000001 +--let $binlog_start= 4 +--source include/show_binlog_events.inc + +--echo *** Test that binlog N is active, and commit checkpoint for (N-1) is +--echo *** done while there is still a pending commit checkpoint for (N-2). + +connection con1; +SET DEBUG_SYNC= "commit_after_group_release_commit_ordered SIGNAL con1_ready WAIT_FOR con1_continue"; +send INSERT INTO t1 VALUES (20, REPEAT("x", 4100)); + +connection default; +SET DEBUG_SYNC= "now WAIT_FOR con1_ready"; + +connection con2; +SET DEBUG_SYNC= "commit_after_group_release_commit_ordered SIGNAL con2_ready WAIT_FOR con2_continue"; +send INSERT INTO t1 VALUES (21, REPEAT("x", 4100)); + +connection default; +SET DEBUG_SYNC= "now WAIT_FOR con2_ready"; +--source include/show_binary_logs.inc +--let $binlog_file= master-bin.000001 +--source include/show_binlog_events.inc +--let $binlog_file= master-bin.000002 +--source include/show_binlog_events.inc +--let $binlog_file= master-bin.000003 +--source include/show_binlog_events.inc + +# We need to sync the test case with the background processing of the +# commit checkpoint, otherwise we get nondeterministic results. +SET DEBUG_SYNC= "RESET"; +SET @old_dbug= @@global.DEBUG_DBUG; +SET GLOBAL debug_dbug="+d,binlog_background_checkpoint_processed"; + +SET DEBUG_SYNC= "now SIGNAL con2_continue"; + +connection con2; +reap; + +connection default; +--echo con1 is still pending, no new binlog checkpoint should have been logged. +# Make sure commit checkpoint is processed before we check that no checkpoint +# event has been binlogged. +SET DEBUG_SYNC= "now WAIT_FOR binlog_background_checkpoint_processed"; +SET GLOBAL debug_dbug= @old_dbug; +SET DEBUG_SYNC= "RESET"; + +--let $binlog_file= master-bin.000003 +--source include/show_binlog_events.inc + +SET DEBUG_SYNC= "now SIGNAL con1_continue"; + +connection con1; +reap; + +connection default; + +--echo No commit checkpoints are pending, a new binlog checkpoint should have been logged. +--let $binlog_file= master-bin.000003 + +# Wait for the master-bin.000003 binlog checkpoint to appear. +--let $wait_for_all= 0 +--let $show_statement= SHOW BINLOG EVENTS IN "$binlog_file" +--let $field= Info +--let $condition= = "master-bin.000003" +--source include/wait_show_condition.inc + +--source include/show_binlog_events.inc + + +--echo *** MDEV-4322: Broken XID counting during binlog rotation *** + +# Test that binlog shutdown waits for any pending binlog checkpoints to have time to complete. + +connection default; +# We will use debug_sync to setup a wait inside the background processing +# of binlog checkpoints. The wait is newer resumed, and will eventually +# time out. If server shutdown does not wait for checkpoint processing to +# complete, we will get an assert. +# +# It is a bit tricky to inject the wait properly as it has to happen in a +# background thread during shutdown. So we first inject a DBUG to set the +# debug_sync wait in the correct thread, then wait to be signalled that +# the inject happened so that we can remove it again from DBUG (else +# check_testcase will complain). + +SET @old_dbug= @@global.DEBUG_DBUG; +SET GLOBAL debug_dbug="+d,inject_binlog_background_thread_before_mark_xid_done"; + +FLUSH LOGS; +INSERT INTO t1 VALUES (30, REPEAT("x", 4100)); +SET DEBUG_SYNC= "now WAIT_FOR injected_binlog_background_thread"; +SET GLOBAL debug_dbug= @old_dbug; +INSERT INTO t1 VALUES (31, REPEAT("x", 4100)); +--source include/show_binary_logs.inc +SET debug_sync = 'reset'; + +SET GLOBAL max_binlog_size= @old_max_binlog_size; +SET GLOBAL innodb_flush_log_at_trx_commit= @old_innodb_flush_log_at_trx_commit; + +--source include/shutdown_mysqld.inc +--source include/start_mysqld.inc + + +--echo *** MDEV-7402: 'reset master' hangs, waits for signalled COND_xid_list *** + + +connect(con3,localhost,root,,); +# Make the binlog background thread wait before clearing the pending checkpoint. +# The bug was that one RESET MASTER would clear the reset_master_pending +# flag set by another RESET MASTER; this could cause the wakeup from the +# binlog background thread not to be sent, and thus the second RESET MASTER +# to wait infinitely. +SET debug_sync="reset_logs_after_set_reset_master_pending SIGNAL reset_master_ready WAIT_FOR reset_master_cont"; +send RESET MASTER; + +--connection default +SET @old_dbug= @@global.DEBUG_DBUG; +SET GLOBAL debug_dbug="+d,inject_binlog_background_thread_before_mark_xid_done"; +SET debug_sync="now WAIT_FOR reset_master_ready"; +RESET MASTER; +SET debug_sync="now WAIT_FOR injected_binlog_background_thread"; +SET GLOBAL debug_dbug=@old_dbug; +SET debug_sync="now SIGNAL reset_master_cont"; + +--connection con3 +REAP; + +--connection default +SET debug_sync = 'reset'; + +--echo *** MDEV-24660: MYSQL_BIN_LOG::cleanup(): Assertion `b->xid_count == 0' failed in MYSQL_BIN_LOG::cleanup +# Test a scenario of forcibly rolled back mixed engine "unsafe" transaction +# at shutdown. That should not let to the assert. + +SET @old_max_binlog_size= @@global.max_binlog_size; +SET GLOBAL max_binlog_size= 4096; + +--connect(con_24660,localhost,root,,) + +# Construct an unsafe xa transaction that is rolled back +# in binlog at the shutdown time. That requires STATEMENT binlog format. +FLUSH LOGS; +--let $binlog_file = query_get_value(SHOW MASTER STATUS, File, 1) +SET @@session.binlog_format = STATEMENT; +CREATE TABLE tm (a INT) ENGINE = myisam; + +call mtr.add_suppression("Table './test/tm' is marked as crashed"); +call mtr.add_suppression("Checking table"); + +XA START 'xa1'; + --let $a = `SELECT a + 1 FROM t1` + --eval INSERT INTO t1 VALUES ($a, 1) + INSERT INTO tm SET a = 1; + --inc $a + --let $repeat_x = `SELECT REPEAT("x", 4100)` +--disable_query_log + --eval INSERT INTO t1 VALUES ($a, "$repeat_x") +--enable_query_log +XA END 'xa1'; + +--connection default + # In the patch's base BBT would exit first to win the race against + # the XA transaction's binloging. + SET GLOBAL debug_dbug="+d,only_kill_system_threads_no_loop"; +--source include/shutdown_mysqld.inc +--source include/start_mysqld.inc + +--echo ** Proof of shutdown caused ROLLBACK-completed transaction + +--let assert_file=$MYSQLTEST_VARDIR/tmp/binlog_decoded.out +--let datadir=`select @@datadir` + +--echo # MYSQL_BINLOG datadir/binlog_file --result-file=assert_file +--exec $MYSQL_BINLOG $datadir/$binlog_file --result-file=$assert_file + +--let $assert_text= No XA statements should be written into the binary log +--let $assert_count= 0 +--let assert_select= XA START|XA END|XA PREPARE|XA COMMIT|XA ROLLBACK +--source include/assert_grep.inc + +--let $assert_text= The transaction should be rolled back +--let $assert_count= 1 +--let assert_select= ^ROLLBACK\$ +--source include/assert_grep.inc + +SELECT * FROM tm; +--eval SELECT * FROM t1 WHERE a = $a + +# Clean up. +DROP TABLE t1, t2, tm; diff --git a/mysql-test/suite/binlog/t/binlog_checkpoint_flush_logs.test b/mysql-test/suite/binlog/t/binlog_checkpoint_flush_logs.test new file mode 100644 index 00000000..e21f1eb3 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_checkpoint_flush_logs.test @@ -0,0 +1,79 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/have_binlog_format_row.inc + +# References: +# +# MDEV-24526 binlog rotate via FLUSH LOGS may obsolate binlog file too eary +# +# The test for MDEV-24526 proves the fixes correct observed race condition +# between a commiting transaction and FLUSH-LOGS. +# The plot. +# Trx_1 (con1) transaction binlogs first +# to yield its turn acquiring LOCK_commit_ordered to Trx_2 and stand +# still waiting of a signal that will never arrive. +# Trx_2 can't acquire it in the fixed version even though +# Trx_3 makes sure Trx_2 has reached a post-rotation execution point +# to signal it to proceed. +# Then the server gets crashed and Trx_1 must recover unlike +# in the OLD buggy version. +# +SET GLOBAL innodb_flush_log_at_trx_commit= 1; +RESET MASTER; + +CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb; + +--echo *** Test that FLUSH LOGS waits if a transaction ordered commit is in progress. + +connect(con1,localhost,root,,); # Trx_1 +# hang before doing acquiring Commit Ordered mutex +SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL con1_ready WAIT_FOR con1_go"; + +--send INSERT INTO t1 VALUES (1, REPEAT("x", 1)) + +connection default; # Trx_2 + +SET DEBUG_SYNC= "now WAIT_FOR con1_ready"; +SET DEBUG_SYNC= "rotate_after_rotate SIGNAL con_flush_ready WAIT_FOR default_go"; +--send FLUSH LOGS + +connect(con2,localhost,root,,); # Trx_3 +--echo Trx_1 is not yet committed: +SELECT count(*) as 'ZERO' from t1; + +--echo Wait for Trx_2 has rotated binlog: +SET DEBUG_SYNC= "now WAIT_FOR con_flush_ready"; +# Useless signal to prove Trx_2 cannot race Trx_1's commit +# even though Trx_1 never received the being waited 'con1_go'. +SET DEBUG_SYNC= "now SIGNAL default_go"; + +--let $shutdown_timeout=0 +--source include/restart_mysqld.inc + +connection default; +--enable_reconnect +--error 0,2013 +--reap + +--echo Must be tree logs in the list: +--source include/show_binary_logs.inc +--let $binlog_file= master-bin.000001 +--let $binlog_start= 4 +--source include/show_binlog_events.inc + +--echo Only one Binlog checkpoint must exist and point to master-bin.000001 +--let $binlog_file= master-bin.000002 +--let $binlog_start= 4 +--source include/show_binlog_events.inc + + +# In the buggy server version the following select may have +# resulted with ZERO: +SELECT count(*) as 'ONE' from t1; + +# Clean up. +connection default; + +DROP TABLE t1; +SET debug_sync = 'reset'; diff --git a/mysql-test/suite/binlog/t/binlog_checksum.test b/mysql-test/suite/binlog/t/binlog_checksum.test new file mode 100644 index 00000000..7ecb9308 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_checksum.test @@ -0,0 +1,37 @@ +source include/have_innodb.inc; +source include/have_log_bin.inc; + +# +# WL#2540 replication event checksum +# +# Objectives of the test are: +# to demo binlog events with CRC32 checksum in them and +# to prove show binlog events and mysqlbinlog are capable to handle +# the checksum. +# + +set @save_binlog_checksum = @@global.binlog_checksum; +set @save_master_verify_checksum = @@global.master_verify_checksum; +set @@global.binlog_checksum = CRC32; +set @@global.master_verify_checksum = 1; +let $MYSQLD_DATADIR= `select @@datadir`; + +reset master; +--echo must be master-bin.000001 +--source include/show_binary_logs.inc + +create table t1 (a int); +flush logs; +drop table t1; + +--source include/show_binlog_events.inc +--exec $MYSQL_BINLOG -c $MYSQLD_DATADIR/master-bin.000001 | $MYSQL +show tables; + +# clean-up + +drop table t1; +set @@global.binlog_checksum = @save_binlog_checksum; +set @@global.master_verify_checksum = @save_master_verify_checksum; + +--echo End of the tests diff --git a/mysql-test/suite/binlog/t/binlog_commit_wait.test b/mysql-test/suite/binlog/t/binlog_commit_wait.test new file mode 100644 index 00000000..7d7af2a9 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_commit_wait.test @@ -0,0 +1,229 @@ +--source include/have_innodb.inc +--source include/have_log_bin.inc + +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; + +SET @old_count= @@GLOBAL.binlog_commit_wait_count; +SET GLOBAL binlog_commit_wait_count= 3; +SET @old_usec= @@GLOBAL.binlog_commit_wait_usec; +SET GLOBAL binlog_commit_wait_usec= 20000000; + +connect(con1,localhost,root,,test); +connect(con2,localhost,root,,test); +connect(con3,localhost,root,,test); + +# Get Initial status measurements +--connection default +SELECT variable_value INTO @group_commits FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commits'; +SELECT variable_value INTO @group_commit_trigger_count FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commit_trigger_count'; +SELECT variable_value INTO @group_commit_trigger_timeout FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commit_trigger_timeout'; +SELECT variable_value INTO @group_commit_trigger_lock_wait FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commit_trigger_lock_wait'; + +# Note: binlog_group_commits is counted at the start of the group and group_commit_trigger_* is +# counted near when the groups its finalised. + +# Check that if T2 goes to wait for a row lock of T1 while T1 is waiting for +# more transactions to arrive for group commit, the commit of T1 will complete +# immediately. +# We test this by setting a very high timeout (20 seconds), and testing that +# that much time does not elapse. + +--connection default +SET @a= current_timestamp(); + +--connection con1 +BEGIN; +INSERT INTO t1 VALUES (1,0); +send COMMIT; + +--connection con2 +send INSERT INTO t1 VALUES (1,1); + +--connection con1 +reap; + +--connection default +SET @b= unix_timestamp(current_timestamp()) - unix_timestamp(@a); +SELECT IF(@b < 20, "Ok", CONCAT("Error: too much time elapsed: ", @b, " seconds >= 20")); + +# All connections are to the same server. One transaction occurs on con1. It is +# commited before con2 is started. con2 transaction violates the unique key contraint. This +# type of group commit is binlog_group_commit_trigger_lock_wait so that further con2 +# transactions will occur afterwards as they may be as result of the ER_DUP_ENTRY on the +# application side. +# before: binlog_group_commit=0, binlog_group_commit_trigger_count=0 +# before: binlog_group_commit_trigger_timeout=0, binlog_group_commit_trigger_lock_wait=0 +# after: binlog_group_commit+1 by reason of binlog_group_commit_trigger_lock_wait+1 +SELECT variable_value - @group_commits FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commits'; +SELECT variable_value - @group_commit_trigger_count FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commit_trigger_count'; +SELECT variable_value - @group_commit_trigger_timeout FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commit_trigger_timeout'; +SELECT variable_value - @group_commit_trigger_lock_wait FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commit_trigger_lock_wait'; + +--connection con2 +--error ER_DUP_ENTRY +reap; + + +# Test that the commit triggers when sufficient commits have queued up. +--connection default +SET @a= current_timestamp(); + +--connection con1 +send INSERT INTO t1 VALUES (2,0); + +--connection con2 +send INSERT INTO t1 VALUES (3,0); + +--connection con3 +INSERT INTO t1 VALUES (4,0); + +--connection con1 +reap; +--connection con2 +reap; + +--connection default +SET @b= unix_timestamp(current_timestamp()) - unix_timestamp(@a); +SELECT IF(@b < 20, "Ok", CONCAT("Error: too much time elapsed: ", @b, " seconds >= 20")); + +# All connections are to the same server. 3 non-conflicting transaction occur +# on each connection. The binlog_commit_wait_count=3 at the start therefore 1 +# group is committed by virtue of reaching 3 transactions. Hence +# binlog_group_commit_trigger_count is incremented. +# before: binlog_group_commit=1, binlog_group_commit_trigger_count=0 +# before: binlog_group_commit_trigger_timeout=0, binlog_group_commit_trigger_lock_wait=1 +# after: binlog_group_commit+1 by reason of binlog_group_commit_trigger_count+1 +SELECT variable_value - @group_commits FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commits'; +SELECT variable_value - @group_commit_trigger_count FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commit_trigger_count'; +SELECT variable_value - @group_commit_trigger_timeout FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commit_trigger_timeout'; +SELECT variable_value - @group_commit_trigger_lock_wait FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commit_trigger_lock_wait'; + +# Test that commit triggers immediately if there is already a transaction +# waiting on another transaction that reaches its commit. + +--connection default +SET @a= current_timestamp(); + +--connection con1 +send INSERT INTO t1 VALUES (6,0); + +--connection con2 +BEGIN; +UPDATE t1 SET b=b+1 WHERE a=1; + +--connection con3 +send UPDATE t1 SET b=b+10 WHERE a=1; + +--connection con2 +# A small sleep to let con3 have time to wait on con2. +# The sleep might be too small on loaded host, but that is not a big problem; +# it only means we will trigger a different code path (con3 waits after con2 +# is ready to commit rather than before); and either path should work the same. +# So we will not get false positive in case of different timing; at worst false +# negative. +SELECT SLEEP(0.25); +UPDATE t1 SET b=b+1 WHERE a=3; +COMMIT; + +--connection con1 +reap; + +--connection default +SET @b= unix_timestamp(current_timestamp()) - unix_timestamp(@a); +SELECT IF(@b < 20, "Ok", CONCAT("Error: too much time elapsed: ", @b, " seconds >= 20")); + +# All connections are to the same server. con2 and con3 updates are aquiring +# the same row lock for a=1. Either con2 or con3 will be in a lock wait +# thefore the binlog_group_commit_trigger_lock_wait is incremented. +# before: binlog_group_commit=2, binlog_group_commit_trigger_count=1 +# before: binlog_group_commit_trigger_timeout=0, binlog_group_commit_trigger_lock_wait=1 +# after: binlog_group_commit+1 by reason of binlog_group_commit_trigger_lock_wait+1 +SELECT variable_value - @group_commits FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commits'; +SELECT variable_value - @group_commit_trigger_count FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commit_trigger_count'; +SELECT variable_value - @group_commit_trigger_timeout FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commit_trigger_timeout'; +SELECT variable_value - @group_commit_trigger_lock_wait FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commit_trigger_lock_wait'; + +--connection default +SET @a= current_timestamp(); + +# Now con3 will be waiting for a following group commit to trigger. +--connection con1 +send INSERT INTO t1 VALUES (7,0); +--connection con2 +INSERT INTO t1 VALUES (8,0); +--connection con3 +reap; + +--connection default +SET @b= unix_timestamp(current_timestamp()) - unix_timestamp(@a); +SELECT IF(@b < 20, "Ok", CONCAT("Error: too much time elapsed: ", @b, " seconds >= 20")); + +# The con1 and con2 transactions above are combined with the 'send UPDATE t1 SET b=b+10 WHERE a=1;' +# on con3 from the previous block. So we have 3 so this is a count based group. +# before: binlog_group_commit=3, binlog_group_commit_trigger_count=1 +# before: binlog_group_commit_trigger_timeout=0, binlog_group_commit_trigger_lock_wait=2 +# after: binlog_group_commit+1 by reason of binlog_group_commit_trigger_count+1 +SELECT variable_value - @group_commits FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commits'; +SELECT variable_value - @group_commit_trigger_count FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commit_trigger_count'; +SELECT variable_value - @group_commit_trigger_timeout FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commit_trigger_timeout'; +SELECT variable_value - @group_commit_trigger_lock_wait FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commit_trigger_lock_wait'; + +# Test that when the binlog_commit_wait_usec is reached the tranction gets a group commit + +--connection default +SET @a= current_timestamp(); +SET GLOBAL binlog_commit_wait_usec= 5*1000*1000; + +--connection con1 +reap; +INSERT INTO t1 VALUES (9,0); + +--connection default +SET @b= unix_timestamp(current_timestamp()) - unix_timestamp(@a); +SELECT IF(@b < 4, CONCAT("Error: too little time elapsed: ", @b, " seconds < 4"), + IF(@b < 20, "Ok", CONCAT("Error: too much time elapsed: ", @b, " seconds >= 20"))); + +# con1 pushes 1 transaction. The count was for 3 to occur before a group commit. +# The timeout is 5 seconds but we allow between 4 and 20 because of the fragile nature +# of time in test. This is a timeout causing the commit so binlog_group_commit_trigger_timeout +# is incremented. +# before: binlog_group_commit=4, binlog_group_commit_trigger_count=2 +# before: binlog_group_commit_trigger_timeout=0, binlog_group_commit_trigger_lock_wait=2 +# after: binlog_group_commit+1 by reason of binlog_group_commit_trigger_timeout+1 +SELECT variable_value - @group_commits FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commits'; +SELECT variable_value - @group_commit_trigger_count FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commit_trigger_count'; +SELECT variable_value - @group_commit_trigger_timeout FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commit_trigger_timeout'; +SELECT variable_value - @group_commit_trigger_lock_wait FROM information_schema.global_status + WHERE variable_name = 'binlog_group_commit_trigger_lock_wait'; + +--connection default +SELECT * FROM t1 ORDER BY a; + +--connection default +DROP TABLE t1; +SET GLOBAL binlog_commit_wait_count= @old_count; +SET GLOBAL binlog_commit_wait_usec= @old_usec; diff --git a/mysql-test/suite/binlog/t/binlog_database.test b/mysql-test/suite/binlog/t/binlog_database.test new file mode 100644 index 00000000..8d298b8a --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_database.test @@ -0,0 +1,15 @@ +# A wrapper to test that dropping a database is binlogged +# correctly. We test all three modes in the same file to avoid +# unecessary server restarts. + +--source include/have_innodb.inc +--source include/have_binlog_format_statement.inc + +set binlog_format=statement; +source include/database.test; +set binlog_format=mixed; +source include/database.test; +set binlog_format=row; +source include/database.test; + +show databases; diff --git a/mysql-test/suite/binlog/t/binlog_delete_and_flush_index-master.opt b/mysql-test/suite/binlog/t/binlog_delete_and_flush_index-master.opt new file mode 100644 index 00000000..434bd66d --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_delete_and_flush_index-master.opt @@ -0,0 +1 @@ +--log-bin=master-bin --log-bin-index=master-bin diff --git a/mysql-test/suite/binlog/t/binlog_delete_and_flush_index.test b/mysql-test/suite/binlog/t/binlog_delete_and_flush_index.test new file mode 100644 index 00000000..84c83687 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_delete_and_flush_index.test @@ -0,0 +1,114 @@ +# BUG#34582: FLUSH LOGS does not close and reopen the binlog index +# file +# +# WHAT +# ==== +# +# We want to test that FLUSH LOGS closes and reopens binlog index +# file. +# +# HOW +# === +# +# PREPARE: +# 1. create some binlog events +# 2. show index content, binlog events and binlog contents +# for mysql-bin.000001 +# 3. copy the mysql-bin.000001 to mysql-bin-b34582.000001 +# 4. change the index file so that mysql-bin.000001 is replaced +# with mysql-bin-b34582.000001 +# 5. FLUSH the logs so that new index is closed and reopened +# +# ASSERTIONS: +# 1. index file contents shows mysql-bin-b34582.000001 and +# mysql-bin.000002 +# 1. show binary logs shows current index entries +# 2. binlog contents for mysql-bin-b34582.000001 are displayed +# 3. Purge binlogs up to the latest one succeeds +# 4. SHOW BINARY LOGS presents the latest one only after purging +# 5. Purged binlogs files don't exist in the filesystem +# 6. Not purged binlog file exists in the filesystem +# +# CLEAN UP: +# 1. RESET MASTER +# + +-- source include/have_log_bin.inc + +RESET MASTER; + +-- let $datadir= `SELECT @@datadir` +-- let $index=$datadir/master-bin.index +-- chmod 0644 $index + +# action: issue one command so that binlog gets some event +CREATE TABLE t1 (a int); + +-- echo ### assertion: index file contains regular entries +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +--echo ### assertion: show original binlogs +-- source include/show_binary_logs.inc + +--echo ### assertion: binlog contents from regular entries +-- source include/show_binlog_events.inc + +# action: copy binlogs to other names and change entries in index file +-- copy_file $datadir/master-bin.000001 $datadir/master-bin-b34582.000001 +let INDEX_FILE=$index; +perl; +$file= $ENV{'INDEX_FILE'}; +open(FILE, ">$file") || die "Unable to open $file."; +truncate(FILE,0); +close ($file); +EOF + +-- append_file $index +master-bin-b34582.000001 +EOF + +# action: should cause rotation, and creation of new binlogs +FLUSH LOGS; + +# file is not used anymore - remove it (mysql closed on flush logs). +-- remove_file $datadir/master-bin.000001 + +-- echo ### assertion: index file contains renamed binlog and the new one +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +-- echo ### assertion: original binlog content still exists, despite we +-- echo ### renamed and changed the index file +-- source include/show_binlog_events.inc + +-- echo ### assertion: user changed binlog index shows correct entries +-- source include/show_binary_logs.inc + +DROP TABLE t1; + +-- echo ### assertion: purging binlogs up to binlog created after instrumenting index file should work +-- let $current_binlog= query_get_value(SHOW MASTER STATUS, File, 1) +-- eval PURGE BINARY LOGS TO '$current_binlog' + +-- echo ### assertion: show binary logs should only contain latest binlog +-- source include/show_binary_logs.inc + +-- echo ### assertion: assert that binlog files were indeed purged (using file_exists calls) +-- error 1 +-- file_exists $datadir/master-bin-b34852.000001 + +-- echo ### assertion: assert that not purged binlog file exists +-- file_exists $datadir/$current_binlog + +-- echo ### assertion: show index file contents and these should match show binary logs issued above +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +RESET MASTER; diff --git a/mysql-test/suite/binlog/t/binlog_dmls_on_tmp_tables_readonly.test b/mysql-test/suite/binlog/t/binlog_dmls_on_tmp_tables_readonly.test new file mode 100644 index 00000000..dd0cdd0f --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_dmls_on_tmp_tables_readonly.test @@ -0,0 +1,92 @@ +# ==== Purpose ==== +# +# Check that DMLs are allowed on temporary tables, when server is in read only +# mode and binary log is enabled with binlog-format being stmt/mixed mode. +# +# ==== Implementation ==== +# +# Start the server with binary log being enabled. Mark the server as read only. +# Create a non-SUPER user and let the user to create a temporary table and +# perform DML operations on that temporary table. DMLs should not be blocked +# with a 'server read-only mode' error. +# +# ==== References ==== +# +# Bug#12818255: READ-ONLY OPTION DOES NOT ALLOW INSERTS/UPDATES ON TEMPORARY +# TABLES +# Bug#14294223: CHANGES NOT ALLOWED TO TEMPORARY TABLES ON READ-ONLY SERVERS +############################################################################### +--source include/have_log_bin.inc +--source include/have_innodb.inc +--disable_warnings +DROP TABLE IF EXISTS t1 ; +--enable_warnings + +--enable_connect_log +--echo # READ_ONLY does nothing to SUPER users +--echo # so we use a non-SUPER one: +CREATE USER test@localhost; +GRANT CREATE TEMPORARY TABLES, SELECT, DROP ON *.* TO test@localhost; + +connect (con1,localhost,test,,test); + +connection default; +SET GLOBAL READ_ONLY=1; + +connection con1; +CREATE TEMPORARY TABLE t1 (a INT) ENGINE=INNODB; + +--echo # Test INSERTS with autocommit being off and on. +BEGIN; +INSERT INTO t1 VALUES (10); +COMMIT; +INSERT INTO t1 VALUES (20); + +--echo # Test UPDATES with autocommit being off and on. +BEGIN; +UPDATE t1 SET a=30 WHERE a=10; +COMMIT; +UPDATE t1 SET a=40 WHERE a=20; + +connection default; +SET GLOBAL READ_ONLY=0; + +--echo # Test scenario where global read_only is enabled in the middle of transaction. +--echo # Test INSERT operations on temporary tables, INSERTs should be successful even +--echo # when global read_only is enabled. +connection con1; +BEGIN; +INSERT INTO t1 VALUES(50); + +connection default; +SET GLOBAL READ_ONLY=1; + +connection con1; +SELECT @@GLOBAL.READ_ONLY; +COMMIT; + +connection default; +SET GLOBAL READ_ONLY=0; + +--echo # Test UPDATE operations on temporary tables, UPDATEs should be successful even +--echo # when global read_only is enabled. +connection con1; +BEGIN; +UPDATE t1 SET a=60 WHERE a=50; + +connection default; +SET GLOBAL READ_ONLY=1; + +connection con1; +SELECT @@GLOBAL.READ_ONLY; +COMMIT; + +SELECT * FROM t1; + +--echo # Clean up +connection default; +SET GLOBAL READ_ONLY=0; + +disconnect con1; +DROP USER test@localhost; +--disable_connect_log diff --git a/mysql-test/suite/binlog/t/binlog_drop_if_exists.test b/mysql-test/suite/binlog/t/binlog_drop_if_exists.test new file mode 100644 index 00000000..b565104c --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_drop_if_exists.test @@ -0,0 +1,162 @@ +--source include/have_innodb.inc + +# BUG#13684: +# SP: DROP PROCEDURE|FUNCTION IF EXISTS not binlogged if routine +# does not exist +# +# There is an inconsistency with DROP DATABASE IF EXISTS, DROP +# TABLE IF EXISTS and DROP VIEW IF EXISTS: those are binlogged even +# if the DB or TABLE does not exist, whereas DROP PROCEDURE IF +# EXISTS does not. It would be nice or at least consistent if DROP +# PROCEDURE/STATEMENT worked the same too. +# +# Description: +# DROP PROCEDURE|FUNCTION IF EXISTS does not get binlogged whereas DROP +# DATABASE|TABLE|TRIGGER|... IF EXISTS do. +# +# Fixed DROP PROCEDURE|FUNCTION IF EXISTS by adding a call to +# write_bin_log in mysql_execute_command. Checked also if all +# documented "DROP (...) IF EXISTS" get binlogged. Left out DROP +# SERVER IF EXISTS because it seems that it only gets binlogged when +# using row event (see BUG#25705). +# +# TODO: add DROP SERVER IF EXISTS to the test case when its +# binlogging procedure gets fixed (BUG#25705). Furthermore, when +# logging in RBR format the events that get logged are effectively in +# RBR format and not in STATEMENT format meaning that one must needs +# to be extra careful when writing a test for it, or change the CREATE +# SERVER logging to always log as STATEMENT. You can quickly check this +# by enabling the flag below $fixed_bug_25705=1 and watch the diff on +# the STDOUT. More detail may be found on the generated reject file. +# +# Test is implemented as follows: +# +# i) test each "drop if exists" (DDL), found in MySQL 5.1 manual, +# on inexistent objects (except for DROP SERVER); +# ii) show binlog events; +# iii) create an object for each drop if exists statement; +# iv) issue "drop if exists" in existent objects. +# v) show binlog events; +# +# References: +# http://dev.mysql.com/doc/refman/5.1/en/sql-syntax-data-definition.html +# +--source include/have_log_bin.inc +RESET MASTER; + +disable_warnings; + +# test all "drop if exists" in manual with inexistent objects +DROP PROCEDURE IF EXISTS db_bug_13684.p; +DROP FUNCTION IF EXISTS db_bug_13684.f; +DROP TRIGGER IF EXISTS db_bug_13684.tr; +DROP VIEW IF EXISTS db_bug_13684.v; +DROP EVENT IF EXISTS db_bug_13684.e; +DROP TABLE IF EXISTS db_bug_13684.t; +DROP DATABASE IF EXISTS db_bug_13684; + +let $fixed_bug_25705 = 0; + +if($fixed_bug_25705) +{ + DROP SERVER IF EXISTS s_bug_13684; +} +--source include/show_binlog_events.inc + +# test drop with existing values + +# create +CREATE DATABASE db_bug_13684; + +CREATE TABLE db_bug_13684.t (a int); + +CREATE EVENT db_bug_13684.e + ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR + DO + UPDATE db_bug_13684.t SET a = a + 1; + +CREATE VIEW db_bug_13684.v + AS SELECT * FROM db_bug_13684.t; + +CREATE TRIGGER db_bug_13684.tr BEFORE INSERT ON db_bug_13684.t + FOR EACH ROW BEGIN + END; + +CREATE PROCEDURE db_bug_13684.p (OUT p1 INT) + BEGIN + END; + +CREATE FUNCTION db_bug_13684.f (s CHAR(20)) + RETURNS CHAR(50) DETERMINISTIC + RETURN s; + +if($fixed_bug_25705) +{ + CREATE SERVER s_bug_13684 + FOREIGN DATA WRAPPER mysql + OPTIONS (USER 'Remote', HOST '192.168.1.106', DATABASE 'test'); +} + +--source include/show_binlog_events.inc + +# drop existing +DROP PROCEDURE IF EXISTS db_bug_13684.p; +DROP FUNCTION IF EXISTS db_bug_13684.f; +DROP TRIGGER IF EXISTS db_bug_13684.tr; +DROP VIEW IF EXISTS db_bug_13684.v; +DROP EVENT IF EXISTS db_bug_13684.e; +DROP TABLE IF EXISTS db_bug_13684.t; +DROP DATABASE IF EXISTS db_bug_13684; +if($fixed_bug_25705) +{ + DROP SERVER IF EXISTS s_bug_13684; +} + +--source include/show_binlog_events.inc + +enable_warnings; + +# Drop comments in binlog +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +CREATE TABLE t1(id int); +DROP TABLE /* comment */ t1; +CREATE TABLE t1(id int); +DROP TABLE IF EXISTS /* comment */ t1; + +CREATE TABLE t1(id int); +DROP TABLE /**/ t1; +CREATE TABLE t1(id int); +DROP TABLE IF EXISTS /* */ t1; + +--source include/show_binlog_events.inc + +--echo # +--echo # MDEV-22820 Bogus "Unknown table" warnings produced upon attempt to +--echo # drop parent table referenced by FK +--echo # + +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); + +create table t1 (a int, key(a)) engine=InnoDB; +create table t2 (b int, foreign key(b) references t1(a)) engine=InnoDB; +--error ER_ROW_IS_REFERENCED_2 +drop table if exists t1; +--error ER_ROW_IS_REFERENCED_2 +drop table if exists t1,t0; +show warnings; +drop table t2,t1; + +create table t3 (a int) engine=aria; + +# This is not logged +--error ER_BAD_TABLE_ERROR +drop table t10,t20; +# This is logged +--error ER_BAD_TABLE_ERROR +drop table t10,t20,t3; + +# These are both logged +drop table if exists t10,t20; +drop table if exists t10,t20,t3; + +--source include/show_binlog_events.inc diff --git a/mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test b/mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test new file mode 100644 index 00000000..501403f4 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test @@ -0,0 +1,148 @@ +# The test verifies execution and binary logging of user XA that produce empty +# XA-PREPARE group of events. + +--source include/have_binlog_format_mixed.inc +--source include/have_innodb.inc + +RESET MASTER; # clear binlogs +# MDEV-22420 DDL on temporary object is prohibited when XA is in prepare state + +# Temporary sequnce may not be created within a transaction +CREATE TEMPORARY SEQUENCE seq_1; + +XA START '3'; +CREATE TEMPORARY TABLE tmp_1(c INT); +XA END '3'; +XA PREPARE '3'; +--error ER_XAER_RMFAIL +DROP TEMPORARY TABLE tmp_1; +--error ER_XAER_RMFAIL +ALTER TABLE tmp_1 DROP COLUMN c; +--error ER_XAER_RMFAIL +DROP TEMPORARY SEQUENCE seq_1; +--error ER_XAER_RMFAIL +ALTER SEQUENCE seq_1 INCREMENT BY 1; + +--error ER_XAER_RMFAIL +CREATE TEMPORARY TABLE tmp_2(c INT); +--error ER_XAER_RMFAIL +CREATE TEMPORARY SEQUENCE seq_2; + +# Cleanup +XA ROLLBACK '3'; + +--echo # Proof of correct logging incl empty XA-PREPARE +--source include/show_binlog_events.inc + +# The test verifies execution and binary logging of user XA that produce empty +# XA-PREPARE group of events. +# +# MDEV-22757 Assertion `!binlog || exist_hton_without_prepare' +# in MYSQL_BIN_LOG::unlog_xa_prepare + +RESET MASTER; +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +INSERT INTO t2 VALUES (1),(2); + +XA START '1'; +REPLACE INTO t1 SELECT * FROM t1; +REPLACE INTO t2 SELECT * FROM t2; +XA END '1'; +XA PREPARE '1'; + +# Cleanup +XA ROLLBACK '1'; +DROP TABLE t1, t2; + +--echo # Proof of correct logging incl empty XA-PREPARE +--source include/show_binlog_events.inc + + +# MDEV-22430 Assertion ... in MYSQL_BIN_LOG::unlog_xa_prepare + +RESET MASTER; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +CREATE SEQUENCE s ENGINE=InnoDB; + +XA START '2'; +--disable_ps2_protocol +SELECT NEXT VALUE FOR s; +--enable_ps2_protocol +REPLACE INTO t1 SELECT * FROM t1; +XA END '2'; +XA PREPARE '2'; + +# Cleanup +XA ROLLBACK '2'; +DROP SEQUENCE s; +DROP TABLE t1; + +--echo # Proof of correct logging incl empty XA-PREPARE +--source include/show_binlog_events.inc + + +# MDEV-25616 Binlog event for XA COMMIT is generated without matching XA START + +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--source include/count_sessions.inc +--connect(con1,localhost,root,,) + +XA START '1'; + --error ER_DUP_ENTRY + INSERT INTO t1 VALUES (2),(1); + SELECT * FROM t1 WHERE a = 2; +XA END '1'; +XA PREPARE '1'; + +--disconnect con1 + +--connection default +--source include/wait_until_count_sessions.inc +XA RECOVER; + +--error ER_XA_RBROLLBACK +XA COMMIT '1'; +--echo Must be no XA PREPARE group nor XA completion one: +--source include/show_binlog_events.inc +DROP TABLE t1; + +--source include/count_sessions.inc + +--connect(con2,localhost,root,,) +CREATE TABLE tm (a INT PRIMARY KEY) ENGINE=MyISAM; +XA START '1'; + --error ER_DUP_ENTRY + INSERT INTO tm VALUES (1),(1); + SELECT * FROM tm WHERE a = 2; +XA END '1'; +XA PREPARE '1'; + +--disconnect con2 + +--connection default +--source include/wait_until_count_sessions.inc +XA RECOVER; + +--error ER_XA_RBROLLBACK +XA ROLLBACK '1'; +--echo Must be no XA PREPARE group nor XA completion one: +--source include/show_binlog_events.inc +DROP TABLE tm; + + +# MDEV-32257 dangling XA-rollback in binlog from emtpy XA +--connection default +--let $binlog_start = query_get_value(SHOW MASTER STATUS, Position, 1) +--let $binlog_file = query_get_value(SHOW MASTER STATUS, File, 1) +SET pseudo_slave_mode=1; +XA START 'a'; +XA END 'a'; +XA PREPARE 'a'; +--error ER_XA_RBROLLBACK +XA ROLLBACK 'a'; +--source include/show_binlog_events.inc diff --git a/mysql-test/suite/binlog/t/binlog_expire_logs_seconds.test b/mysql-test/suite/binlog/t/binlog_expire_logs_seconds.test new file mode 100644 index 00000000..bb53f2c4 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_expire_logs_seconds.test @@ -0,0 +1,122 @@ +# +# WL#9236: Add a new variable binlog_expire_logs_seconds +# +# ==== Purpose ==== +# The test case test the following: +# +# 1. If binlog_expire_logs_seconds = 0 and expire_logs_days = 0, no purge happens. +# +# 2. In all the below listed cases it purges the binary logs older than the timeout +# and keeps the binary logs newer than the timeout. +# +# 2.1. binlog_expire_logs_seconds > 0 and expire_logs_days > 0 +# 2.2. binlog_expire_logs_seconds > 0 and expire_logs_days = 0 +# 2.3. binlog_expire_logs_seconds = 0 and expire_logs_days > 0 +# 2.4. binlog_expire_logs_seconds = 1, testing smallest value +# 2.5. binlog_expire_logs_seconds = 8553600, testing max value 99days +# +# Additional tests for the boundaries of expire_logs_days already +# exist on the sys_vars.expire_logs_days_basic test case. + +# Test in this file is binlog format agnostic, thus no need +# to rerun it for every format. +--source include/have_binlog_format_row.inc +--source include/not_windows.inc + +--let $saved_expire_logs_days= `SELECT @@GLOBAL.expire_logs_days` +--let $saved_binlog_expire_logs_seconds= `SELECT @@GLOBAL.binlog_expire_logs_seconds` +# Set the datadir +--let $MYSQLD_DATADIR= `SELECT @@datadir` + +--echo #### +--echo #### 1. When binlog_expire_logs_seconds == 0 and expire_logs_days == 0 +--echo #### no purge should happen + +SET GLOBAL binlog_expire_logs_seconds= 0; +SET GLOBAL expire_logs_days= 0; + +# This will test the expire period for three scenarios, described in the .inc file. +--source suite/binlog/include/binlog_expire_logs_seconds.inc + +--echo #### +--echo #### 2.1: binlog_expire_logs_seconds > 0 and expire_logs_days > 0 +--echo #### expire_logs_days=1.5 and binlog_expire_logs_seconds=86400 +--echo #### Since binlog_expire_logs_seconds is set later +--echo #### expire_logs_days value will be overridden should be +--echo #### '0.000347222' +--echo #### + +# Here we will test both with smaller values and larger values + +--echo Testing with smaller values of binlog_expire_logs_seconds + +SET GLOBAL expire_logs_days= 1.5; +SET GLOBAL binlog_expire_logs_seconds= 30 ; +SELECT @@expire_logs_days as 'Expected_0.000347222'; +SELECT @@binlog_expire_logs_seconds as Expected_30; + +--let $expire_logs_seconds= `SELECT @@global.binlog_expire_logs_seconds` + +--let $first_binlog_file= query_get_value(SHOW MASTER STATUS, File, 1) +FLUSH LOGS; + +--sleep $expire_logs_seconds + +--let $second_binlog_file= query_get_value(SHOW MASTER STATUS, File, 1) +FLUSH LOGS; + +# The sleep is in two parts to ensure a time gap between first_binlog_file +# and second_binlog_file, by doing that we can check that one is purged and +# another isn't. +# sleep for n seconds here, n < $expire_logs_seconds +--sleep 3 +FLUSH LOGS; + +--error 1 +--file_exists $MYSQLD_DATADIR/$first_binlog_file + +--file_exists $MYSQLD_DATADIR/$second_binlog_file + +RESET MASTER; +--echo #### +--echo #### 2.2: binlog_expire_logs_seconds = 43200 and expire_logs_days = 0 +--echo #### + +SET GLOBAL expire_logs_days=0; +SET GLOBAL binlog_expire_logs_seconds=43200; +SELECT @@expire_logs_days as 'Expected_0.5'; +SELECT @@binlog_expire_logs_seconds as Expected_43200; + +# This will test the expire period for three scenarios, described in the .inc file. + +--source suite/binlog/include/binlog_expire_logs_seconds.inc + +--echo #### +--echo #### 2.3: binlog_expire_logs_seconds == 0 and expire_logs_days > 0 +--echo #### + +SET GLOBAL binlog_expire_logs_seconds= 0; +SET GLOBAL expire_logs_days= 1; +SELECT @@expire_logs_days as Expected_1; +SELECT @@binlog_expire_logs_seconds as Expected_86400; + +# This will test the expire period for three scenarios, described in the .inc file. +--source suite/binlog/include/binlog_expire_logs_seconds.inc + +--echo #### +--echo #### 2.4: binlog_expire_logs_seconds = 1 +--echo #### +SET GLOBAL binlog_expire_logs_seconds= 1; +SELECT @@expire_logs_days; +SELECT @@binlog_expire_logs_seconds as Expected_1; + +--echo #### +--echo #### 2.5. binlog_expire_logs_seconds = 8553600, testing max value 99days +--echo #### +SET GLOBAL binlog_expire_logs_seconds= 8553600; +SELECT @@expire_logs_days; +SELECT @@binlog_expire_logs_seconds as Expected_8553600; + +# reset the variables +--eval SET GLOBAL binlog_expire_logs_seconds= $saved_binlog_expire_logs_seconds +--eval SET GLOBAL expire_logs_days= $saved_expire_logs_days diff --git a/mysql-test/suite/binlog/t/binlog_expire_warnings.test b/mysql-test/suite/binlog/t/binlog_expire_warnings.test new file mode 100644 index 00000000..2e0831ad --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_expire_warnings.test @@ -0,0 +1,200 @@ +# ==== Requirements ==== +# +# Verify the logic for warnings related to expire-logs-days and +# binlog-expire-logs-seconds on server start: +# +# R0. All the following shall hold with binlog disabled and binlog enabled. +# +# R1. Binlog off warnings: +# +# R1.1. If the binary log is disabled, using any of +# binlog-expire-logs-seconds or expire_logs_days shall +# generate a warning. +# +# R1.2. If the binary log is enabled, or if +# binlog-expire-logs-seconds / expire_logs_days is not used, +# there shall be no warning for this case. +# +# R2. Values: +# +# R2.1. None of expire-logs-days or binlog-expire-logs-seconds is +# set: both shall use their default values (days=0, seconds=0) +# +# R2.2. Exactly one of expire-logs-days or binlog-expire-logs-seconds +# is set: that value is propogated to other variable. +# +# R2.3. Both expire-logs-days or binlog-expire-logs-seconds are +# set, and at least one of them is set to zero: the last set value +# should be effective and its value will be propogated to other +# variable. +# +# R2.4. Both expire-logs-days and binlog-expire-logs-seconds are +# set, and both are non-zero: the last set value +# should be effective and its value will be propogated to other +# variable. +# +# ==== Implementation ==== +# +# Test all combinations of: +# +# - log-bin: on, off +# - expire-logs-days: not set, set to 0, set to nonzero +# - binlog-expire-logs-seconds: not set, set to 0, set to nonzero +# - Verify option value propogation, by varying the order, in which options +# are set +# --expire_logs_days --binlog_expire_logs_seconds +# --binlog_expire_logs_seconds --expire_logs_days +# For each such scenario, state the expected warnings and values, and +# use extra/binlog_tests/binlog_expire_warnings.inc to execute the +# scenario. +# +# ==== References ==== +# +# MDEV-19371: Implement binlog_expire_logs_seconds for purging of binary +# logs +# +--source include/have_binlog_format_row.inc + +# Restarts the server with new options. +--source include/force_restart.inc + +# A bit slow, since it restarts the server many times. Also, this is +# unlikely to break in the future, so not important to run frequently. +--source include/big_test.inc + + +--let $ofile = $MYSQLTEST_VARDIR/tmp/binlog_expire_warnings-output.err + +--let $i = 0 +while ($i < 2) { + +if ($i == 0) { + --echo #### Binary log ENABLED #### + --let $options = + --let $binlog_off = 0 + } + if ($i == 1) { + --echo #### Binary log DISABLED #### + --let $options = --skip-log-bin + --let $binlog_off = 1 + } + + --echo ==== Don't set any option ==== + + --let $days = + --let $seconds = + --let $expect_binlog_off_days_and_seconds_warning = 0 + --let $expect_days = 0 + --let $expect_seconds = 0 + --source suite/binlog/include/binlog_expire_warnings.inc + + --echo ==== Set one option to zero ==== + + --echo ---- days=0 ---- + --let $days = 0 + --let $seconds = + --let $expect_binlog_off_days_and_seconds_warning = 0 + --let $expect_days = 0 + --let $expect_seconds = 0 + --let $option_invoke_order= days_then_seconds + --source suite/binlog/include/binlog_expire_warnings.inc + + --echo ---- seconds=0 ---- + --let $days = + --let $seconds = 0 + --let $expect_binlog_off_days_and_seconds_warning = 0 + --let $expect_days = 0 + --let $expect_seconds = 0 + --let $option_invoke_order= seconds_then_days + --source suite/binlog/include/binlog_expire_warnings.inc + + --echo ==== Set one option to non-zero ==== + + --echo ---- days=2 ---- + --let $days = 2 + --let $seconds = + --let $expect_binlog_off_days_and_seconds_warning = $binlog_off + --let $expect_days = 2 + --let $expect_seconds = `SELECT $days * 24 * 60 * 60` + --let $option_invoke_order= days_then_seconds + --source suite/binlog/include/binlog_expire_warnings.inc + + --echo ---- seconds=86400 ---- + --let $days = + --let $seconds = 86400 + --let $expect_binlog_off_days_and_seconds_warning = $binlog_off + --let $expect_days = 1 + --let $expect_seconds = 86400 + --let $option_invoke_order= days_then_seconds + --source suite/binlog/include/binlog_expire_warnings.inc + + --echo ==== Set both options to zero ==== + + --let $days = 0 + --let $seconds = 0 + --let $expect_binlog_off_days_and_seconds_warning = 0 + --let $expect_days = 0 + --let $expect_seconds = 0 + --let $option_invoke_order= days_then_seconds + --source suite/binlog/include/binlog_expire_warnings.inc + + --echo ==== Set both options: one to zero and one to non-zero ==== + --echo ---- days=1 seconds=0 ---- + --echo ---- The later seconds=0 will override days. + --let $days = 1 + --let $seconds = 0 + --let $expect_binlog_off_days_and_seconds_warning = 0 + --let $expect_days = 0 + --let $expect_seconds = 0 + --let $option_invoke_order= days_then_seconds + --source suite/binlog/include/binlog_expire_warnings.inc + + --echo ---- seconds=0 days=1 ---- + --echo ---- The later days=1 will override seconds. + --let $days = 1 + --let $seconds = 0 + --let $expect_binlog_off_days_and_seconds_warning = $binlog_off + --let $expect_days = 1 + --let $expect_seconds = 86400 + --let $option_invoke_order= seconds_then_days + --source suite/binlog/include/binlog_expire_warnings.inc + + --echo ---- days=0 seconds=86400 ---- + --echo ---- The later seconds=86400 will override days. + --let $days = 0 + --let $seconds = 86400 + --let $expect_binlog_off_days_and_seconds_warning = $binlog_off + --let $expect_days = 1 + --let $expect_seconds = 86400 + --let $option_invoke_order= days_then_seconds + --source suite/binlog/include/binlog_expire_warnings.inc + + --echo ==== Set both options to non-zero ==== + + --echo ---- days=1 and seconds=172800 ---- + --echo ---- Since binlog_expire_logs_seconds is set later expire_log_days + --echo ---- becomes 2 + --let $days = 1 + --let $seconds = 172800 + --let $expect_binlog_off_days_and_seconds_warning = $binlog_off + --let $expect_days = 2 + --let $expect_seconds = 172800 + --let $option_invoke_order= days_then_seconds + --source suite/binlog/include/binlog_expire_warnings.inc + + --echo ---- days=1 and seconds=172800 ---- + --echo ---- Since expire_logs_days is set later binlog_expire_logs_seconds + --echo ---- becomes 86400 + --let $days = 1 + --let $seconds = 172800 + --let $expect_binlog_off_days_and_seconds_warning = $binlog_off + --let $expect_days = 1 + --let $expect_seconds = 86400 + --let $option_invoke_order= seconds_then_days + --source suite/binlog/include/binlog_expire_warnings.inc + + --inc $i +} + +# cleanup +--remove_file $ofile diff --git a/mysql-test/suite/binlog/t/binlog_flush_binlogs_delete_domain.test b/mysql-test/suite/binlog/t/binlog_flush_binlogs_delete_domain.test new file mode 100644 index 00000000..1643ecff --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_flush_binlogs_delete_domain.test @@ -0,0 +1,167 @@ +# Prove basic properties of +# +# FLUSH BINARY LOGS DELETE_DOMAIN_ID = (...) +# +# The command removes the supplied list of domains from the current +# @@global.gtid_binlog_state provided the binlog files do not contain +# events from such domains. + +# The test is not format specific. One format is chosen to run it. +--source include/have_binlog_format_mixed.inc + +# Reset binlog state +RESET MASTER; + +# Empty list is accepted +FLUSH BINARY LOGS DELETE_DOMAIN_ID = (); +--echo and the command execution is effective thence rotates binlog as usual +--source include/show_binary_logs.inc + +--echo Non-existed domain is warned, the command completes without rotation +--echo but with a warning +--let $binlog_pre_flush=query_get_value(SHOW MASTER STATUS, Position, 1) +FLUSH BINARY LOGS DELETE_DOMAIN_ID = (99); +--source include/show_binary_logs.inc + +# Log one event in a specified domain and try to delete the domain +SET @@SESSION.gtid_domain_id=1; +SET @@SESSION.server_id=1; +CREATE TABLE t (a int); +SELECT @@GLOBAL.gtid_binlog_state, @@GLOBAL.gtid_binlog_pos; +--let $binlog_start= +--source include/show_binlog_events.inc + +--error ER_BINLOG_CANT_DELETE_GTID_DOMAIN +FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1); + +# the same error after log rotation +FLUSH BINARY LOGS; +--error ER_BINLOG_CANT_DELETE_GTID_DOMAIN +FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1); + +# the latest binlog does not really contain any events incl ones from 1-domain +--let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1) +--eval PURGE BINARY LOGS TO '$purge_to_binlog'; +# So now it's safe to delete +--error 0 +FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1); +--echo Gtid_list of the current binlog does not contain '1': +--let $binlog_file=query_get_value(SHOW MASTER STATUS, File, 1) +--source include/show_gtid_list.inc +--echo But the previous log's Gtid_list may have it which explains a warning from the following command +--let $binlog_file=$purge_to_binlog +--source include/show_gtid_list.inc + +--echo Already deleted domain in Gtid_list of the earliest log is benign +--echo but may cause a warning +--error 0 +FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1); + +# Few domains delete. The chosen number verifies among others how +# expected overrun of the static buffers of underlying dynamic arrays is doing. +--let $domain_cnt=17 +--let $server_in_domain_cnt=3 +--let $err_domain_id=`SELECT FLOOR($domain_cnt/2)` +--let $err_server_id=`SELECT FLOOR($server_in_domain_cnt/2)` +--let $domain_list= +--disable_query_log +while ($domain_cnt) +{ + --let servers=$server_in_domain_cnt + --eval SET @@SESSION.gtid_domain_id=$domain_cnt + while ($servers) + { + --eval SET @@SESSION.server_id=10*$domain_cnt + $servers + --eval INSERT INTO t SET a=@@SESSION.server_id + + --dec $servers + } + --let $domain_list= $domain_cnt, $domain_list + + --dec $domain_cnt +} +--enable_query_log +--let $zero=0 +--let $domain_list= $domain_list$zero + +--error ER_BINLOG_CANT_DELETE_GTID_DOMAIN +--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($domain_list) + +--echo MDEV-31140: Missing error from DELETE_DOMAIN_ID when gtid_binlog_state partially matches GTID_LIST. +FLUSH BINARY LOGS; +--let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1) +--eval PURGE BINARY LOGS TO '$purge_to_binlog' +--eval SET @@SESSION.gtid_domain_id=$err_domain_id +--eval SET @@SESSION.server_id=10*$err_domain_id + $err_server_id +eval INSERT INTO t SELECT 1+MAX(a) FROM t; +--error ER_BINLOG_CANT_DELETE_GTID_DOMAIN +--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($domain_list) + +# Now satisfy the safety condtion to purge log files containing $domain list +FLUSH BINARY LOGS; +--let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1) +--eval PURGE BINARY LOGS TO '$purge_to_binlog' +--error 0 +--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($domain_list) +--echo Gtid_list of the current binlog does not contain $domain_list: +--let $binlog_file=query_get_value(SHOW MASTER STATUS, File, 1) +--source include/show_gtid_list.inc + +# Show reaction on @@global.gtid_binlog_state not succeeding +# earlier state as described by the 1st binlog' Gtid_list. +# Now let it be out-order gtid logged to a domain unrelated to deletion. + +--let $del_d_id=1 +--eval SET @@SESSION.gtid_domain_id=$del_d_id; +SET @@SESSION.server_id=1; +SET @@SESSION.gtid_seq_no=1; +INSERT INTO t SET a=1; +SET @@SESSION.server_id=2; +SET @@SESSION.gtid_seq_no=2; +INSERT INTO t SET a=2; + +SET @@SESSION.gtid_domain_id=11; +SET @@SESSION.server_id=11; +SET @@SESSION.gtid_seq_no=11; +INSERT INTO t SET a=11; + +SET @gtid_binlog_state_saved=@@GLOBAL.gtid_binlog_state; +FLUSH BINARY LOGS; + +# Inject out of order for domain '11' before +SET @@SESSION.gtid_domain_id=11; +SET @@SESSION.server_id=11; +SET @@SESSION.gtid_seq_no=1; +INSERT INTO t SET a=1; + +SELECT @gtid_binlog_state_saved "as original state", @@GLOBAL.gtid_binlog_state as "out of order for 11 domain state"; + +# to delete '1', first to purge logs containing its events +--let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1) +--eval PURGE BINARY LOGS TO '$purge_to_binlog' + +--echo the following command succeeds with warnings +--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($del_d_id) + +# cleanup: forget the out-of-order +RESET MASTER; + +# +# MDEV-14431 +# Check rejection to delete a domain with value exceeding its range's maximum +# +--let $d_max_plus_1=`SELECT 1 << 32` +--error ER_BINLOG_CANT_DELETE_GTID_DOMAIN +--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($d_max_plus_1) + +# accepted maximum: +--let $d_max=`SELECT (1 << 32) - 1` +--error 0 +--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($d_max) + +# +# Cleanup +# + +DROP TABLE t; +RESET MASTER; diff --git a/mysql-test/suite/binlog/t/binlog_format_switch_in_tmp_table.test b/mysql-test/suite/binlog/t/binlog_format_switch_in_tmp_table.test new file mode 100644 index 00000000..68685060 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_format_switch_in_tmp_table.test @@ -0,0 +1,76 @@ +# +# Bug #45855 row events in binlog after switch from binlog_fmt=mix to stmt with open tmp tbl +# Bug #45856 can't switch from binlog_format=row to mix with open tmp tbl +# This test verfies if the program will generate ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR +# error and forbid switching @@SESSION.binlog_format from MIXED or ROW to +# STATEMENT when there are open temp tables and we are logging in row format. +# There is no error in any other case. +# + +source include/have_binlog_format_mixed.inc; + +SELECT @@SESSION.binlog_format; +CREATE TABLE t1 (a VARCHAR(100)); +CREATE TEMPORARY TABLE t2 (a VARCHAR(100)); + +--echo # Test allow switching @@SESSION.binlog_format from MIXED to STATEMENT +--echo # when there are open temp tables and we are logging in statement based format. +SET SESSION binlog_format = STATEMENT; +SELECT @@SESSION.binlog_format; + +--echo # Test allow switching @@SESSION.binlog_format from STATEMENT to +--echo # STATEMENT when there are open temp tables. +SET SESSION binlog_format = STATEMENT; +SELECT @@SESSION.binlog_format; + +INSERT INTO t1 VALUES ('statement based'); +SELECT @@SESSION.binlog_format; +--echo # Test allow switching @@SESSION.binlog_format from STATEMENT to +--echo # MIXED when there are open temp tables. +SET SESSION binlog_format = MIXED; +SELECT @@SESSION.binlog_format; + +--echo # Test allow switching @@SESSION.binlog_format from MIXED to MIXED +--echo # when there are open temp tables. +SET SESSION binlog_format = MIXED; +SELECT @@SESSION.binlog_format; + +INSERT INTO t2 VALUES (UUID()); +SELECT @@SESSION.binlog_format; + +--echo # Test forbit switching @@SESSION.binlog_format from MIXED to STATEMENT +--echo # when there are open temp tables and we are logging in row based format. +--ERROR ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR +SET SESSION binlog_format = STATEMENT; +SELECT @@SESSION.binlog_format; + +SET SESSION binlog_format = ROW; +SELECT @@SESSION.binlog_format; + +INSERT INTO t1 VALUES ('row based'); +--echo # Test allow switching @@SESSION.binlog_format from ROW to MIXED +--echo # when there are open temp tables. +SET SESSION binlog_format = MIXED; +SELECT @@SESSION.binlog_format; + +INSERT INTO t1 VALUES ('row based'); +--echo # Test allow switching @@SESSION.binlog_format from MIXED to ROW +--echo # when there are open temp tables. +SET SESSION binlog_format = ROW; +SELECT @@SESSION.binlog_format; + +--echo # Test allow switching @@SESSION.binlog_format from ROW to ROW +--echo # when there are open temp tables. +SET SESSION binlog_format = ROW; +SELECT @@SESSION.binlog_format; + +INSERT INTO t1 VALUES ('row based'); +--echo # Test forbit switching @@SESSION.binlog_format from ROW to STATEMENT +--echo # when there are open temp tables. +--ERROR ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR +SET SESSION binlog_format = STATEMENT; +SELECT @@SESSION.binlog_format; + +DROP TEMPORARY TABLE t2; +DROP TABLE t1; + diff --git a/mysql-test/suite/binlog/t/binlog_grant.test b/mysql-test/suite/binlog/t/binlog_grant.test new file mode 100644 index 00000000..d573281f --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_grant.test @@ -0,0 +1,216 @@ +# Test grants for various objects (especially variables) related to +# the binary log + +source include/have_log_bin.inc; + +connection default; +--disable_warnings +reset master; +--enable_warnings + +set @saved_binlog_format = @@global.binlog_format; +create user mysqltest_1@localhost; +GRANT SELECT on test.* to mysqltest_1@localhost; +show grants for mysqltest_1@localhost; + +connect (plain,localhost,mysqltest_1,,test); +connect (root,localhost,root,,test); + +# Testing setting session SQL_LOG_BIN variable both as +# root and as plain user. + +--echo **** Variable SQL_LOG_BIN **** + +connection root; +--echo [root] +set session sql_log_bin = 1; + +connection plain; +--echo [plain] +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +set session sql_log_bin = 1; + + +# Testing setting both session and global BINLOG_FORMAT variable both +# as root and as plain user. + +--echo **** Variable BINLOG_FORMAT **** + +connection root; +--echo [root] +set global binlog_format = row; +set session binlog_format = row; + +connection plain; +--echo [plain] +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +set global binlog_format = row; +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +set session binlog_format = row; + +--echo **** Clean up **** +disconnect plain; +disconnect root; + +connection default; +set global binlog_format = @saved_binlog_format; +drop user mysqltest_1@localhost; + + +# Testing if REPLICATION CLIENT privilege is enough to execute +# SHOW MASTER LOGS and SHOW BINARY. +CREATE USER 'mysqltest_1'@'localhost'; +GRANT REPLICATION CLIENT ON *.* TO 'mysqltest_1'@'localhost'; +--connect(rpl,localhost,mysqltest_1,,"*NO-ONE*") + +--connection rpl +# We are only interested if the following commands succeed and not on +# their output. +--disable_result_log +SHOW MASTER LOGS; +SHOW BINARY LOGS; +SHOW BINLOG STATUS; +--enable_result_log + +# clean up +--disconnect rpl +connection default; +DROP USER 'mysqltest_1'@'localhost'; + + +--echo # +--echo # Start of 10.5 test +--echo # + +--echo # +--echo # MDEV-21743 Split up SUPER privilege to smaller privileges +--echo # + +--echo # Test that REPLICATION CLIENT is an alias for BINLOG MONITOR + +CREATE USER user1@localhost; +GRANT REPLICATION CLIENT ON *.* TO user1@localhost; +SHOW GRANTS FOR user1@localhost; +REVOKE REPLICATION CLIENT ON *.* FROM user1@localhost; +SHOW GRANTS FOR user1@localhost; +DROP USER user1@localhost; + + +--echo # Test if SHOW BINARY LOGS and SHOW BINGLOG STATUS are not allowed without REPLICATION CLIENT or SUPER +CREATE USER user1@localhost; +GRANT ALL PRIVILEGES ON *.* TO user1@localhost; +REVOKE REPLICATION CLIENT, SUPER ON *.* FROM user1@localhost; +--connect(user1,localhost,user1,,) +--connection user1 +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +SHOW MASTER LOGS; +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +SHOW BINARY LOGS; +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +SHOW BINLOG STATUS; +--disconnect user1 +--connection default +DROP USER user1@localhost; + + +--echo # Test if PURGE BINARY LOGS is not allowed without BINLOG ADMIN or SUPER +CREATE USER user1@localhost; +GRANT ALL PRIVILEGES ON *.* TO user1@localhost; +REVOKE BINLOG ADMIN, SUPER ON *.* FROM user1@localhost; +--connect(user1,localhost,user1,,) +--connection user1 +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +PURGE BINARY LOGS BEFORE '2001-01-01 00:00:00'; +--disconnect user1 +--connection default +DROP USER user1@localhost; + + +--echo # Test if PURGE BINLOG is allowed with BINLOG ADMIN +CREATE USER user1@localhost; +GRANT BINLOG ADMIN ON *.* TO user1@localhost; +--connect(user1,localhost,user1,,"*NO-ONE*") +--connection user1 +PURGE BINARY LOGS BEFORE '2001-01-01 00:00:00'; +--disconnect user1 +connection default; +DROP USER user1@localhost; + + +--echo # Test if PURGE BINLOG is allowed with SUPER +CREATE USER user1@localhost; +GRANT SUPER ON *.* TO user1@localhost; +--connect(user1,localhost,user1,,"*NO-ONE*") +--connection user1 +PURGE BINARY LOGS BEFORE '2001-01-01 00:00:00'; +--disconnect user1 +connection default; +DROP USER user1@localhost; + + +--echo # Test if SHOW BINLOG EVENTS is not allowed without BINLOG MONITOR +CREATE USER user1@localhost; +GRANT ALL PRIVILEGES ON *.* TO user1@localhost; +REVOKE BINLOG MONITOR ON *.* FROM user1@localhost; +--connect(user1,localhost,user1,,) +--connection user1 +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +SHOW BINLOG EVENTS; +--disconnect user1 +--connection default +DROP USER user1@localhost; + + +--echo # Test if SHOW BINLOG EVENTS is allowed with BINLOG MONITOR +CREATE USER user1@localhost; +GRANT BINLOG MONITOR ON *.* TO user1@localhost; +--connect(user1,localhost,user1,,"*NO-ONE*") +--connection user1 +--disable_result_log +SHOW BINLOG EVENTS; +--enable_result_log +--disconnect user1 +connection default; +DROP USER user1@localhost; + +--echo # +--echo # MDEV-21975 Add BINLOG REPLAY privilege and bind new privileges to +--echo # gtid_seq_no, preudo_thread_id, server_id, gtid_domain_id +--echo # +--echo # Test combinations of BINLOG REPLAY guarded features which typically +--echo # arise in mysqlbinlog output replay on server. +--echo # + +CREATE USER user1@localhost; +GRANT BINLOG REPLAY ON *.* TO user1@localhost; +GRANT ALL ON test.* TO user1@localhost; +RESET MASTER; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +--connect(user1,localhost,user1,,) +# Genuine mysqlbinlog output +--exec $MYSQL_BINLOG --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql +RENAME TABLE t1 to t2; + +--exec $MYSQL --user=user1 test < $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql + +--connection default +REVOKE BINLOG REPLAY ON *.* FROM user1@localhost; +call mtr.add_suppression("Access denied; you need (at least one of) the SUPER, BINLOG REPLAY privilege(s) for this operation"); +--echo # Privilege errors are expected now: +--connection user1 +--error 1 +--exec $MYSQL --user=user1 test < $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql + +--connection default +--let $diff_tables=t1,t2 +--source include/diff_tables.inc + +--echo # Test cleanup +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql +DROP TABLE t2,t1; +DROP USER user1@localhost; + +--echo # +--echo # End of 10.5 test +--echo # diff --git a/mysql-test/suite/binlog/t/binlog_gtid_delete_domain_debug.test b/mysql-test/suite/binlog/t/binlog_gtid_delete_domain_debug.test new file mode 100644 index 00000000..5de549c4 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_gtid_delete_domain_debug.test @@ -0,0 +1,11 @@ +# Check "internal" error branches of +# FLUSH BINARY LOGS DELETE_DOMAIN_ID = (...) +# handler. +--source include/have_debug.inc +--source include/have_binlog_format_mixed.inc + +SET @@SESSION.debug_dbug='+d,inject_binlog_delete_domain_init_error'; +--error ER_BINLOG_CANT_DELETE_GTID_DOMAIN +FLUSH BINARY LOGS DELETE_DOMAIN_ID = (99); + +SHOW WARNINGS; diff --git a/mysql-test/suite/binlog/t/binlog_implicit_commit.test b/mysql-test/suite/binlog/t/binlog_implicit_commit.test new file mode 100644 index 00000000..11ceae5f --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_implicit_commit.test @@ -0,0 +1,63 @@ +# The purpose of this test is to test that setting autocommit does a +# commit of outstanding transactions and nothing is left pending in +# the transaction cache. + +source include/have_log_bin.inc; +source include/have_innodb.inc; + +# We need a transactional engine, so let's use InnoDB +CREATE TABLE t1 (id INT) ENGINE = InnoDB; + +# Testing SET AUTOCOMMIT +SET BINLOG_FORMAT = STATEMENT; + +let $cleanup = COMMIT; + +let $prepare = SET AUTOCOMMIT = 0; +let $statement = SET AUTOCOMMIT = 1; +source include/implicit.test; + +let $prepare = SET AUTOCOMMIT = 1; +let $statement = SET AUTOCOMMIT = 1; +source include/implicit.test; + +let $prepare = SET AUTOCOMMIT = 0; +let $statement = SET AUTOCOMMIT = 0; +source include/implicit.test; + +let $prepare = SET AUTOCOMMIT = 1; +let $statement = SET AUTOCOMMIT = 0; +source include/implicit.test; + +SET BINLOG_FORMAT = ROW; +let $prepare = SET AUTOCOMMIT = 0; +let $statement = SET AUTOCOMMIT = 1; +source include/implicit.test; + +let $prepare = SET AUTOCOMMIT = 1; +let $statement = SET AUTOCOMMIT = 1; +source include/implicit.test; + +let $prepare = SET AUTOCOMMIT = 0; +let $statement = SET AUTOCOMMIT = 0; +source include/implicit.test; + +let $prepare = SET AUTOCOMMIT = 1; +let $statement = SET AUTOCOMMIT = 0; +source include/implicit.test; + +RESET MASTER; +SET AUTOCOMMIT = 0; +INSERT INTO t1 VALUES (1); +source include/show_binlog_events.inc; +LOCK TABLES t1 WRITE; +source include/show_binlog_events.inc; +INSERT INTO t1 VALUES (2); +source include/show_binlog_events.inc; +UNLOCK TABLES; +source include/show_binlog_events.inc; +COMMIT; +source include/show_binlog_events.inc; + +# Cleaning up +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/binlog_incident.test b/mysql-test/suite/binlog/t/binlog_incident.test new file mode 100644 index 00000000..de7abf20 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_incident.test @@ -0,0 +1 @@ +--source include/binlog_incident.inc diff --git a/mysql-test/suite/binlog/t/binlog_index-master.opt b/mysql-test/suite/binlog/t/binlog_index-master.opt new file mode 100644 index 00000000..c3754b4d --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_index-master.opt @@ -0,0 +1 @@ +--loose-skip-stack-trace --log-warnings=0 --log-bin=master-bin --log-bin-index=master-bin diff --git a/mysql-test/suite/binlog/t/binlog_index.test b/mysql-test/suite/binlog/t/binlog_index.test new file mode 100644 index 00000000..a7c4ce8f --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_index.test @@ -0,0 +1 @@ +--source include/binlog_index.inc diff --git a/mysql-test/suite/binlog/t/binlog_innodb.opt b/mysql-test/suite/binlog/t/binlog_innodb.opt new file mode 100644 index 00000000..2d4e658e --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_innodb.opt @@ -0,0 +1 @@ +--binlog_cache_size=32768 --binlog_stmt_cache_size=32768 diff --git a/mysql-test/suite/binlog/t/binlog_innodb.test b/mysql-test/suite/binlog/t/binlog_innodb.test new file mode 100644 index 00000000..5f372e6d --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_innodb.test @@ -0,0 +1,204 @@ +source include/have_innodb.inc; +source include/have_log_bin.inc; + +SET BINLOG_FORMAT=MIXED; + +RESET MASTER; + +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=INNODB; +INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4),(5,5),(6,6); + +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +BEGIN; +# Should be logged as statement +UPDATE t1 SET b = 2*a WHERE a > 1; +COMMIT; + +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +BEGIN; +# Should be logged as rows +UPDATE t1 SET b = a * a WHERE a > 3; +COMMIT; + +# Check that errors are generated when trying to use READ COMMITTED +# transaction isolation level in STATEMENT binlog mode. + +SET BINLOG_FORMAT=STATEMENT; + +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +BEGIN; +error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE; +UPDATE t1 SET b = 1*a WHERE a > 1; +COMMIT; + +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +BEGIN; +error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE; +UPDATE t1 SET b = 2*a WHERE a > 2; +COMMIT; + +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +BEGIN; +UPDATE t1 SET b = 3*a WHERE a > 3; +COMMIT; + +SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; +BEGIN; +UPDATE t1 SET b = 4*a WHERE a > 4; +COMMIT; + +SET BINLOG_FORMAT=MIXED; + +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +BEGIN; +UPDATE t1 SET b = 1*a WHERE a > 1; +COMMIT; + +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +BEGIN; +UPDATE t1 SET b = 2*a WHERE a > 2; +COMMIT; + +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +BEGIN; +UPDATE t1 SET b = 3*a WHERE a > 3; +COMMIT; + +SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; +BEGIN; +UPDATE t1 SET b = 4*a WHERE a > 4; +COMMIT; + +SET BINLOG_FORMAT=ROW; + +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +BEGIN; +UPDATE t1 SET b = 1*a WHERE a > 1; +COMMIT; + +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +BEGIN; +UPDATE t1 SET b = 2*a WHERE a > 2; +COMMIT; + +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +BEGIN; +UPDATE t1 SET b = 3*a WHERE a > 3; +COMMIT; + +SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; +BEGIN; +UPDATE t1 SET b = 4*a WHERE a > 4; +COMMIT; + +source include/show_binlog_events.inc; + +DROP TABLE t1; + + +# +# Let us test binlog_cache_use and binlog_cache_disk_use status vars. +# Actually this test has nothing to do with innodb per se, it just requires +# transactional table. +# +flush status; +show status like "binlog_cache_use"; +show status like "binlog_cache_disk_use"; + +create table t1 (a int) engine=innodb; + +# Now we are going to create transaction which is long enough so its +# transaction binlog will be flushed to disk... +let $1=2000; +disable_query_log; +begin; +while ($1) +{ + eval insert into t1 values( $1 ); + dec $1; +} +commit; +enable_query_log; +show status like "binlog_cache_use"; +show status like "binlog_cache_disk_use"; + +# Transaction which should not be flushed to disk and so should not +# increase binlog_cache_disk_use. +begin; +delete from t1; +commit; +show status like "binlog_cache_use"; +show status like "binlog_cache_disk_use"; +drop table t1; + +# +# Bug#27716 multi-update did partially and has not binlogged +# + +CREATE TABLE `t1` ( + `a` int(11) NOT NULL auto_increment, + `b` int(11) default NULL, + PRIMARY KEY (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 ; + +CREATE TABLE `t2` ( + `a` int(11) NOT NULL auto_increment, + `b` int(11) default NULL, + PRIMARY KEY (`a`) +) ENGINE=INNODB DEFAULT CHARSET=latin1 ; + +# A. testing multi_update::send_eof() execution branch +insert into t1 values (1,1),(2,2); +insert into t2 values (1,1),(4,4); +reset master; +--error ER_DUP_ENTRY +UPDATE t2,t1 SET t2.a=t1.a+2; +# check +select * from t2 /* must be (3,1), (4,4) */; +--echo # There must no UPDATE in binlog; +source include/show_binlog_events.inc; + +# B. testing multi_update::send_error() execution branch +delete from t1; +delete from t2; +insert into t1 values (1,2),(3,4),(4,4); +insert into t2 values (1,2),(3,4),(4,4); +reset master; +--error ER_DUP_ENTRY +UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a; +--echo # There must be no UPDATE query event; +source include/show_binlog_events.inc; + +# cleanup bug#27716 +drop table t1, t2; + +--echo *** MDEV-11937: InnoDB flushes redo log too often *** + +# Count number of log fsyncs reported by InnoDB per commit. +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; + +SET @old_flush = @@GLOBAL.innodb_flush_log_at_trx_commit; +SET GLOBAL innodb_flush_log_at_trx_commit=1; + +--let $syncs1 = query_get_value(SHOW STATUS LIKE 'Innodb_data_fsyncs', Value, 1) +--let $ROWS = 100 +--disable_query_log +let $count = $ROWS; +while ($count) { + eval INSERT INTO t1 VALUES ($count); + dec $count; +} +--let $syncs2 = query_get_value(SHOW STATUS LIKE 'Innodb_data_fsyncs', Value, 1) +eval SET @num_sync = $syncs2 - $syncs1; +--enable_query_log + +# Allow a bit of slack, in case some background process or something +# is introducing a few more syncs. +eval SELECT IF(@num_sync < $ROWS*1.5, "OK", + CONCAT("ERROR: More than 1 fsync per commit (saw ", @num_sync/$ROWS, ")")) AS status; + +DROP TABLE t1; +SET GLOBAL innodb_flush_log_at_trx_commit=@old_flush; + + +--echo End of tests diff --git a/mysql-test/suite/binlog/t/binlog_innodb_row.test b/mysql-test/suite/binlog/t/binlog_innodb_row.test new file mode 100644 index 00000000..f4ad1058 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_innodb_row.test @@ -0,0 +1,105 @@ +# +# Tests of innodb/binlog with the row binlog format +# +source include/have_innodb.inc; +source include/have_log_bin.inc; +source include/have_binlog_format_row.inc; + +# +# Bug #40221 Replication failure on RBR + UPDATE the primary key +# + +CREATE TABLE t1 (i int unique) ENGINE=innodb; +reset master; + +# part 1: update can cause the dup key + +begin; +insert into t1 values (1),(2); +--echo *** the following UPDATE query wont generate any updates for the binlog *** +--error ER_DUP_ENTRY +update t1 set i = 3 where i < 3; +commit; + +--echo *** Results of the test: the binlog must have only Write_rows events not any Update_rows *** +source include/show_binlog_events.inc; + +# part 2: insert can cause the dup key + +delete from t1; +reset master; + +begin; +insert into t1 values (1),(2); +--echo *** the following UPDATE query wont generate any updates for the binlog *** +--error ER_DUP_ENTRY +insert into t1 values (3),(4),(1),(2); +commit; + +--echo *** Results of the test: the binlog must have only one Write_rows event not two *** +source include/show_binlog_events.inc; + +drop table t1; + +# +# BUG#51251 +# +# The test case checks if truncating a temporary table created with +# engine InnoDB will not cause the truncate statement to be binlogged. + +# Before patch for BUG#51251, the TRUNCATE statements below would be +# binlogged, which would cause the slave to fail with "table does not +# exist". + +RESET MASTER; + +CREATE TABLE t1 ( c1 int , primary key (c1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1), (2), (3); +CREATE TEMPORARY TABLE IF NOT EXISTS t2 LIKE t1; +TRUNCATE TABLE t2; +DROP TABLE t1; + +-- echo ############################################### +-- echo ### assertion: No event for 'TRUNCATE TABLE t2' +-- echo ############################################### +-- source include/show_binlog_events.inc +-- echo ############################################### + +RESET MASTER; + +CREATE TEMPORARY TABLE t1 (c1 int) Engine=InnoDB; +INSERT INTO t1 VALUES (1), (2), (3); +TRUNCATE t1; +DROP TEMPORARY TABLE t1; + +-- echo ############################################### +-- echo ### assertion: No event for 'TRUNCATE TABLE t1' +-- echo ############################################### +-- source include/show_binlog_events.inc +-- echo ############################################### + + +--echo # +--echo # Bug#12346411 SQL/LOG.CC:6509: ASSERTION `PREPARED_XIDS > 0' FAILED +--echo # + +--disable_warnings +DROP TABLE IF EXISTS t1, t2; +--enable_warnings + +CREATE TABLE t1(a INT PRIMARY KEY) engine=innodb; +CREATE TABLE t2(a INT) engine=myisam; + +INSERT INTO t1 VALUES (1); +START TRANSACTION; +INSERT INTO t2 VALUES (1); +INSERT IGNORE INTO t1 VALUES (1); +COMMIT; + +INSERT INTO t1 VALUES (2); +START TRANSACTION; +INSERT INTO t2 VALUES (2); +UPDATE IGNORE t1 SET a=1 WHERE a=2; +COMMIT; + +DROP TABLE t1, t2; diff --git a/mysql-test/suite/binlog/t/binlog_innodb_stm.test b/mysql-test/suite/binlog/t/binlog_innodb_stm.test new file mode 100644 index 00000000..4dfa7a76 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_innodb_stm.test @@ -0,0 +1,26 @@ +source include/have_innodb.inc; +source include/have_binlog_format_statement.inc; + +# +# MDEV-18466 Unsafe to log updates on tables referenced by foreign keys with triggers in statement format +# + +create table categories( + cat_id int not null primary key, + cat_name varchar(255) not null, + cat_description text +) engine=innodb; + +create table products( + prd_id int not null auto_increment primary key, + prd_name varchar(355) not null, + prd_price decimal, + cat_id int not null, + foreign key fk_cat(cat_id) + references categories(cat_id) + on update cascade +) engine=innodb; + +insert into categories values (1, 'drinks', 'drinks'); +update categories set cat_description=2 where cat_id=1; +drop table products, categories; diff --git a/mysql-test/suite/binlog/t/binlog_invalid_read_in_rotate.combinations b/mysql-test/suite/binlog/t/binlog_invalid_read_in_rotate.combinations new file mode 100644 index 00000000..72076e12 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_invalid_read_in_rotate.combinations @@ -0,0 +1,5 @@ +[enable_checksum] +binlog_checksum=1 + +[disable_checksum] +binlog_checksum=0 diff --git a/mysql-test/suite/binlog/t/binlog_invalid_read_in_rotate.test b/mysql-test/suite/binlog/t/binlog_invalid_read_in_rotate.test new file mode 100644 index 00000000..36bb56c8 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_invalid_read_in_rotate.test @@ -0,0 +1,48 @@ +# ==== Purpose ==== +# +# Test verifies that reading binary log by using "SHOW BINLOG EVENTS" command +# from various random positions doesn't lead to crash. It should exit +# gracefully with appropriate error. +# +# ==== References ==== +# +# MDEV-18046:Assortment of crashes, assertion failures and ASAN errors in mysql_show_binlog_events + +--source include/have_log_bin.inc +--source include/have_innodb.inc + +RESET MASTER; + +call mtr.add_suppression("Error in Log_event::read_log_event*"); +call mtr.add_suppression("Replication event checksum verification failed while reading from a log file*"); + +DROP TABLE /*! IF EXISTS*/ t1; +CREATE TABLE `t1` ( +`col_int` int, +pk integer auto_increment, +`col_char_12_key` char(12), +`col_int_key` int, +`col_char_12` char(12), +primary key (pk), +key (`col_char_12_key` ), +key (`col_int_key` )) ENGINE=InnoDB; + +INSERT /*! IGNORE */ INTO t1 VALUES (183173120, NULL, 'abcd', 1, 'efghijk'), (1, NULL, 'lmno', 2, 'p'); + +--disable_warnings +ALTER TABLE `t1` ENABLE KEYS; +--enable_warnings + +--let $max_pos= query_get_value(SHOW MASTER STATUS,Position,1) +--let $pos= 1 +while ($pos <= $max_pos) +{ + --disable_query_log + --disable_result_log + --error 0,1220 + eval SHOW BINLOG EVENTS FROM $pos; + --inc $pos + --enable_result_log + --enable_query_log +} +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/binlog_ioerr.test b/mysql-test/suite/binlog/t/binlog_ioerr.test new file mode 100644 index 00000000..e75adb19 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_ioerr.test @@ -0,0 +1 @@ +--source include/binlog_ioerr.inc diff --git a/mysql-test/suite/binlog/t/binlog_killed.test b/mysql-test/suite/binlog/t/binlog_killed.test new file mode 100644 index 00000000..7c3a262d --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_killed.test @@ -0,0 +1,457 @@ +-- source include/have_innodb.inc +-- source include/have_binlog_format_statement.inc +-- source include/binlog_start_pos.inc + +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); + +# You cannot use `KILL' with the Embedded MySQL Server library, +# because the embedded server merely runs inside the threads of the host +# application. -- the docs + +-- source include/not_embedded.inc + +# +# Avoid printing binlog checkpoints +# + +--let $skip_checkpoint_events=1 + + +### +### bug#22725 : incorrect killed error in binlogged query +### + +connect (con1, localhost, root,,); +connect (con2, localhost, root,,); + +create table t1 (a int auto_increment, b int, PRIMARY KEY (a)) ENGINE=InnoDB; +create table t2 (a int auto_increment, b int, PRIMARY KEY (a)) ENGINE=MyISAM; +create table t3 (a int auto_increment, b int, PRIMARY KEY (a)) ENGINE=InnoDB; + +# +# effective test for bug#22725 +# + +connection con1; +select get_lock("a", 20); + +connection con2; +let $ID= `select connection_id()`; + +# +# reset master does not reset binlogging on the embedded server. +# the test is not run on the embedded for reason of using KILL query. +# `reset master' problem is to be addressed by bug#15580 fixes. +# +reset master; +send insert into t2 values (null, null), (null, get_lock("a", 10)); + + +connection con1; + +--disable_abort_on_error +--disable_warnings + +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where info like "%insert into t2 values%" and state like 'User lock'; +--source include/wait_condition.inc + +--replace_regex /[0-9]+/ID/ +eval kill query $ID; + +connection con2; +--error 0,ER_QUERY_INTERRUPTED +reap; +let $rows= `select count(*) from t2 /* must be 2 or 0 */`; + +let $MYSQLD_DATADIR= `select @@datadir`; +--let $binlog_killed_pos=query_get_value(SHOW BINLOG EVENTS, Pos, 6) +--let $binlog_killed_end_log_pos=query_get_value(SHOW BINLOG EVENTS, End_log_pos, 6) +--exec $MYSQL_BINLOG --force-if-open --start-position=$binlog_killed_pos --stop-position=$binlog_killed_end_log_pos $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--disable_result_log +eval select +(@a:=load_file("$MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog")) +is not null; +--enable_result_log +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +let $error_code= `select @a like "%#%error_code=0%" /* must return 1 or 0*/`; +let $insert_binlogged= `select @a like "%insert into%" /* must return 1 or 0 */`; +eval set @result= $rows - $error_code - $insert_binlogged; + +--enable_warnings +--enable_abort_on_error + +select @result /* must be zero either way */; + + +--remove_file $MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog +connection con1; +select RELEASE_LOCK("a"); + +# +# bug#27571 asynchronous setting mysql_`query`::error and Query_log_e::error_code +# + +# checking that killing inside of select loops is safe as before +# killing after the loop can be only simulated - another test + +delete from t1; +delete from t2; +insert into t1 values (1,1),(2,2); + +# +# simple update +# +connection con1; +begin; update t1 set b=11 where a=2; + +connection con2; +let $ID= `select connection_id()`; +begin; +send update t1 set b=b+10; + +connection con1; +--replace_result $ID ID +eval kill query $ID; +rollback; + +# Bug #32148 killi query may be ineffective +# forced to comment out the test's outcome +# and mask out ineffective ER_QUERY_INTERRUPTED +# todo1: revert back upon fixing bug#32148 +# todo2: the tests need refining in that +# killing should wait till the victim requested +# its lock (wait_condition available in 5.1 tests) + +connection con2; +--error 0,ER_QUERY_INTERRUPTED +reap; +rollback; +select * from t1 order by a /* must be the same as before (1,1),(2,2) */; + +# +# multi update +# commented out as Bug #31807 multi-update,delete killing does not report with ER_QUERY_INTERRUPTED +# in the way +# +# connection con1; +# begin; update t1 set b=b+10; + +# connection con2; +# send update t1 as t_1,t1 as t_2 set t_1.b=11 where t_2.a=2; + +# connection con1; +# --replace_result $ID ID +# eval kill query $ID; +# rollback; + +# disable_abort_on_error; + +# connection con2; +# --error HY000,ER_QUERY_INTERRUPTED +# reap; +# select * from t1 /* must be the same as before (1,1),(2,2) */; + +# enable_abort_on_error; +# +# simple delete +# +connection con1; +begin; delete from t1 where a=2; + +connection con2; +let $ID= `select connection_id()`; +begin; +send delete from t1 where a=2; + +connection con1; +--replace_result $ID ID +eval kill query $ID; +rollback; + +connection con2; +--error 0,ER_QUERY_INTERRUPTED +reap; +rollback; +# todo1,2 above +select * from t1 order by a /* must be the same as before (1,1),(2,2) */; + + +# +# multi delete +# the same as for multi-update +# +# connection con1; +# begin; delete from t1 where a=2; + +# connection con2; +# send delete t1 from t1 where t1.a=2; + +# connection con1; +# --replace_result $ID ID +# eval kill query $ID; +# rollback; + +# connection con2; +# --error 0,ER_QUERY_INTERRUPTED +# reap; +# select * from t1 /* must be the same as before (1,1),(2,2) */; +# +# insert select +# +connection con1; +--disable_warnings +drop table if exists t4; +--enable_warnings +create table t4 (a int, b int) engine=innodb; +insert into t4 values (3, 3); +begin; insert into t1 values (3, 3); + +connection con2; +let $ID= `select connection_id()`; +begin; +send insert into t1 select * from t4 for update; + +connection con1; +--replace_result $ID ID +eval kill query $ID; +rollback; + +connection con2; +--error 0,ER_QUERY_INTERRUPTED,ER_LOCK_WAIT_TIMEOUT +reap; +# todo 1,2 above +rollback; +select * from t1 /* must be the same as before (1,1),(2,2) */; + +drop table t4; # cleanup for the sub-case + +### +## non-ta table case: killing must be recorded in binlog +### +create table t4 (a int, b int) ENGINE=MyISAM /* for killing update and delete */; + +delimiter |; +create function bug27563(n int) +RETURNS int(11) +NOT DETERMINISTIC +begin + if @b > 0 then + select get_lock("a", 20) into @a; + else + set @b= 1; + end if; + return n; +end| +delimiter ;| + +# +# update +# + +delete from t4; +insert into t4 values (1,1), (1,1); +reset master; +connection con1; +select get_lock("a", 20); + +connection con2; +let $ID= `select connection_id()`; +set @b= 0; +send update t4 set b=b + bug27563(b); + +connection con1; +let $wait_condition= select count(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST where state='User lock'; +source include/wait_condition.inc; +select count(*) FROM INFORMATION_SCHEMA.PROCESSLIST where state='User lock'; + +--replace_result $ID ID +eval kill query $ID; + +connection con2; +--error ER_QUERY_INTERRUPTED +reap; +select * from t4 order by b /* must be (1,1), (1,2) */; +select @b /* must be 1 at the end of a stmt calling bug27563() */; +--echo must have the update query event on the 4th line +source include/show_binlog_events.inc; +--let $binlog_killed_pos= query_get_value(SHOW BINLOG EVENTS, Pos, 5) +--let $binlog_killed_end_log_pos= query_get_value(SHOW BINLOG EVENTS, End_log_pos, 5) + +--echo *** a proof the query is binlogged with an error *** + +--exec $MYSQL_BINLOG --force-if-open --start-position=$binlog_killed_pos --stop-position=$binlog_killed_end_log_pos $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval select +(@a:=load_file("$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog")) +is not null; +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +let $error_code= `select @a like "%#%error_code=0%" /* must return 0*/`; +eval select $error_code /* must return 0 to mean the killed update is in */; + +# cleanup for the sub-case +connection con1; +select RELEASE_LOCK("a"); +--remove_file $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog + +# +# delete +# + +delete from t4; +insert into t4 values (1,1), (2,2); +reset master; +connection con1; +select get_lock("a", 20); + +connection con2; +let $ID= `select connection_id()`; +set @b= 0; +send delete from t4 where b=bug27563(1) or b=bug27563(2); + +connection con1; +let $wait_condition= select count(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST where state='User lock'; +source include/wait_condition.inc; +select count(*) FROM INFORMATION_SCHEMA.PROCESSLIST where state='User lock'; +--replace_result $ID ID +eval kill query $ID; + +connection con2; +--error ER_QUERY_INTERRUPTED +reap; +select count(*) from t4 /* must be 1 */; +select @b /* must be 1 at the end of a stmt calling bug27563() */; +--echo must have the delete query event on the 4th line +source include/show_binlog_events.inc; +--let $binlog_killed_pos= query_get_value(SHOW BINLOG EVENTS, Pos, 5) +--let $binlog_killed_end_log_pos= query_get_value(SHOW BINLOG EVENTS, End_log_pos, 5) + +# a proof the query is binlogged with an error + +--exec $MYSQL_BINLOG --force-if-open --start-position=$binlog_killed_pos --stop-position=$binlog_killed_end_log_pos $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval select +(@a:=load_file("$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog")) +is not null; +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +let $error_code= `select @a like "%#%error_code=0%" /* must return 0*/`; +eval select $error_code /* must return 0 to mean the killed delete is in */; + +# cleanup for the sub-case +connection con1; +select RELEASE_LOCK("a"); +--remove_file $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog + +drop table t4; + +# +# load data - see simulation tests +# + + +# bug#27571 cleanup + +drop function bug27563; + + +# Prove that killing connection in the middle +# of mixed engine transactions affect binlogging +# as specified. + +# keep binlogging for this piece of test in a new file +FLUSH LOGS; + +# Connection con3 as transaction generator thoughout the test +connect (con3, localhost, root,,); + +connection con3; +let $ID= `select connection_id()`; + +--let $threads_connected=`select variable_value from information_schema.global_status where variable_name="threads_connected"` +--let wait_condition=select variable_value < $threads_connected from information_schema.global_status where variable_name="threads_connected" + +--echo MI: MyISAM, INNODB +BEGIN; +INSERT INTO t2 VALUES (NULL, 1); +INSERT INTO t1 VALUES (NULL, 2); + +#Connection con1 as killer throughout the test +connection con1; +--replace_result $ID ID +--eval KILL $ID +let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1); +--source include/wait_condition.inc +--let $binlog_start= 4 +--source include/show_binlog_events.inc +--let $binlog_killed_pos=query_get_value(SHOW MASTER STATUS, Position, 1) + +disconnect con3; +connect (con3, localhost, root,,); +connection con3; +let $ID= `select connection_id()`; + +--echo IM: INNODB, MyISAM +BEGIN; +INSERT INTO t1 VALUES (NULL, 3); +INSERT INTO t2 VALUES (NULL, 4); + +connection con1; +--replace_result $ID ID +--eval KILL $ID +--source include/wait_condition.inc +--let $binlog_start= $binlog_killed_pos +--source include/show_binlog_events.inc +--let $binlog_killed_pos=query_get_value(SHOW MASTER STATUS, Position, 1) + +disconnect con3; +connect (con3, localhost, root,,); +connection con3; +let $ID= `select connection_id()`; + +--echo IMI: INNODB, MyISAM, INNODB +BEGIN; +INSERT INTO t1 VALUES (NULL, 5); +INSERT INTO t2 VALUES (NULL, 6); +INSERT INTO t1 VALUES (NULL, 7); + +connection con1; +--replace_result $ID ID +--eval KILL $ID +--source include/wait_condition.inc +--let $binlog_start= $binlog_killed_pos +--source include/show_binlog_events.inc +--let $binlog_killed_pos=query_get_value(SHOW MASTER STATUS, Position, 1) + +disconnect con3; +connect (con3, localhost, root,,); +connection con3; +let $ID= `select connection_id()`; + +--echo MI2: MyISAM, INNODB, MyISAM, INNODB +BEGIN; +INSERT INTO t2 VALUES (NULL, 8); +INSERT INTO t1 VALUES (NULL, 9); +INSERT INTO t2 VALUES (NULL, 10); +INSERT INTO t1 VALUES (NULL, 11); + +connection con1; +--replace_result $ID ID +--eval KILL $ID +--source include/wait_condition.inc +--let $binlog_start= $binlog_killed_pos +--source include/show_binlog_events.inc + + +# +# common cleanup +# + +connection default; +disconnect con1; +disconnect con2; + +drop table t1,t2,t3; + +--echo end of the tests diff --git a/mysql-test/suite/binlog/t/binlog_killed_simulate-master.opt b/mysql-test/suite/binlog/t/binlog_killed_simulate-master.opt new file mode 100644 index 00000000..90c70ece --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_killed_simulate-master.opt @@ -0,0 +1 @@ +--loose-debug=d,simulate_kill_bug27571 diff --git a/mysql-test/suite/binlog/t/binlog_killed_simulate.test b/mysql-test/suite/binlog/t/binlog_killed_simulate.test new file mode 100644 index 00000000..20f51721 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_killed_simulate.test @@ -0,0 +1,61 @@ +-- source include/have_debug.inc +-- source include/have_binlog_format_statement.inc +-- source include/binlog_start_pos.inc +# +# bug#27571 asynchronous setting mysql_$query()'s local error and +# Query_log_event::error_code +# + +# +# Checking that killing upon successful row-loop does not affect binlogging +# + +create table t1 (a int) engine=MyISAM; +insert into t1 set a=1; +reset master; + +update t1 set a=2 /* will be "killed" after work has been done */; + +# a proof the query is binlogged with no error +let datadir= `select @@datadir`; +--exec $MYSQL_BINLOG --force-if-open --start-position=$binlog_start_pos $datadir/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval set @a:=load_file("$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog"); +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +select @a like '%#%error_code=0%' /* must return 1 as query completed before got killed*/; + +# cleanup for the sub-case +remove_file $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog; + +# +# Checking that killing inside of row-loop for LOAD DATA into +# non-transactional table affects binlogging +# + +create table t2 (a int, b int) ENGINE=MyISAM; +reset master; +--error ER_QUERY_INTERRUPTED +load data infile '../../std_data/rpl_loaddata.dat' into table t2 /* will be "killed" in the middle */; + +# a proof the query is binlogged with an error +--let binlog_load_data= query_get_value(SHOW BINLOG EVENTS, Pos, 5) +--let binlog_end= query_get_value(SHOW BINLOG EVENTS, Pos, 6) +source include/show_binlog_events.inc; + +--mkdir $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571 +--exec $MYSQL_BINLOG --local-load=$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571 --force-if-open --start-position=$binlog_load_data --stop-position=$binlog_end $datadir/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval set @a:=load_file("$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog"); +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +select @a like '%#%error_code=0%' /* must return 0 to mean the killed query is in */; + +# cleanup for the sub-case +remove_file $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog; + +--remove_files_wildcard $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571 * +--rmdir $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571 + +drop table t1,t2; + +--echo end of the tests diff --git a/mysql-test/suite/binlog/t/binlog_max_binlog_stmt_cache_size.opt b/mysql-test/suite/binlog/t/binlog_max_binlog_stmt_cache_size.opt new file mode 100644 index 00000000..c52ef14d --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_max_binlog_stmt_cache_size.opt @@ -0,0 +1 @@ +--max_binlog_stmt_cache_size=18446744073709547520 diff --git a/mysql-test/suite/binlog/t/binlog_max_binlog_stmt_cache_size.test b/mysql-test/suite/binlog/t/binlog_max_binlog_stmt_cache_size.test new file mode 100644 index 00000000..ca3f45c1 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_max_binlog_stmt_cache_size.test @@ -0,0 +1,36 @@ + +--echo # +--echo # MDEV-4774: Strangeness with max_binlog_stmt_cache_size Settings +--echo # + +CALL mtr.add_suppression("unsigned value 18446744073709547520 adjusted to 4294963200"); + +--replace_result 18446744073709547520 MAX_BINLOG_STMT_CACHE_SIZE 4294963200 MAX_BINLOG_STMT_CACHE_SIZE +SELECT @@global.max_binlog_stmt_cache_size; + +# Save the initial value of @@global.max_binlog_stmt_cache_size. +--replace_result 18446744073709547520 MAX_BINLOG_STMT_CACHE_SIZE 4294963200 MAX_BINLOG_STMT_CACHE_SIZE +SET @cache_size= @@max_binlog_stmt_cache_size; + +--disable_warnings +SET @@global.max_binlog_stmt_cache_size= @cache_size+1; +--enable_warnings +--replace_result 18446744073709547520 MAX_BINLOG_STMT_CACHE_SIZE 4294963200 MAX_BINLOG_STMT_CACHE_SIZE +SELECT @@global.max_binlog_stmt_cache_size; + +--disable_warnings +SET @@global.max_binlog_stmt_cache_size = @cache_size+4095; +--enable_warnings +--replace_result 4294963200 MAX_BINLOG_STMT_CACHE_SIZE 18446744073709547520 MAX_BINLOG_STMT_CACHE_SIZE +SELECT @@global.max_binlog_stmt_cache_size; + +--disable_warnings +SET @@global.max_binlog_stmt_cache_size= @cache_size-1; +--enable_warnings +SELECT @@global.max_binlog_stmt_cache_size = @cache_size-4096; + +# Restore @@global.max_binlog_stmt_cache_size to its initial value. +SET @@global.max_binlog_stmt_cache_size= @cache_size; + +--echo # End of test + diff --git a/mysql-test/suite/binlog/t/binlog_max_extension.test b/mysql-test/suite/binlog/t/binlog_max_extension.test new file mode 100644 index 00000000..81e35744 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_max_extension.test @@ -0,0 +1,87 @@ +# BUG#40611: MySQL cannot make a binary log after sequential number beyond +# unsigned long. +# +# Problem statement +# ================= +# +# Extension for log file names might be created with negative +# numbers (when counter used would wrap around), causing server +# failure when incrementing -00001 (reaching number 000000 +# extension). +# +# Test +# ==== +# This tests aims at testing the a patch that removes negatives +# numbers from log name extensions and checks that the server +# reports gracefully that the limit has been reached. +# +# It instruments index file to point to a log file close to +# the new maximum and calls flush logs to get warning. +# + +call mtr.add_suppression("Next log extension: 2147483647. Remaining log filename extensions: 0."); +call mtr.add_suppression("Log filename extension number exhausted:"); +call mtr.add_suppression("Can't generate a unique log-filename"); + + +-- source include/have_log_bin.inc +RESET MASTER; + +-- let $MYSQLD_DATADIR= `select @@datadir` +-- let $log_bin_index=`select substring_index(@@log_bin_index,'/',-1)` +-- let $log_bin_basename=`select substring_index(@@log_bin_basename,'/',-1)` + +############################################### +# check hitting maximum file name extension: +############################################### + +########## +# Prepare +########## + +# 1. Stop master server +-- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +-- shutdown_server +-- source include/wait_until_disconnected.inc + +# 2. Prepare log and index file +-- copy_file $MYSQLD_DATADIR/$log_bin_index $MYSQLD_DATADIR/$log_bin_index.orig +-- copy_file $MYSQLD_DATADIR/$log_bin_basename.000001 $MYSQLD_DATADIR/$log_bin_basename.2147483646 +-- append_file $MYSQLD_DATADIR/$log_bin_index +master-bin.2147483646 +EOF + +# 3. Restart the server +-- exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +-- enable_reconnect +-- source include/wait_until_connected_again.inc + +########### +# Assertion +########### + +# assertion: should raise error +-- error ER_NO_UNIQUE_LOGFILE +FLUSH LOGS; + +############## +# Clean up +############## + +# 1. Stop the server +-- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +-- shutdown_server +-- source include/wait_until_disconnected.inc + +# 2. Undo changes to index and log files +-- remove_file $MYSQLD_DATADIR/$log_bin_index +-- copy_file $MYSQLD_DATADIR/$log_bin_index.orig $MYSQLD_DATADIR/$log_bin_index +-- remove_file $MYSQLD_DATADIR/$log_bin_index.orig + +-- remove_file $MYSQLD_DATADIR/$log_bin_basename.2147483646 +-- remove_file $MYSQLD_DATADIR/$log_bin_basename.2147483647 + +# 3. Restart the server +-- exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +-- enable_reconnect +-- source include/wait_until_connected_again.inc diff --git a/mysql-test/suite/binlog/t/binlog_mdev342-master.opt b/mysql-test/suite/binlog/t/binlog_mdev342-master.opt new file mode 100644 index 00000000..590d44a6 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mdev342-master.opt @@ -0,0 +1 @@ +--loose-skip-stack-trace --skip-core-file diff --git a/mysql-test/suite/binlog/t/binlog_mdev342.test b/mysql-test/suite/binlog/t/binlog_mdev342.test new file mode 100644 index 00000000..6d48ea12 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mdev342.test @@ -0,0 +1,67 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/have_binlog_format_row.inc +# Valgrind does not work well with test that crashes the server +--source include/not_valgrind.inc + +# (We do not need to restore these settings, as we crash the server). +SET GLOBAL max_binlog_size= 4096; +SET GLOBAL innodb_flush_log_at_trx_commit= 1; +RESET MASTER; + +CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb; +# MDEV-515 takes X-lock on the table for the first insert +# In that case, Concurrent DML will get blocked +INSERT INTO t1 VALUES(100, "MDEV-515"); +# One connection does an insert that causes a binlog rotate. +# The rotate is paused after writing new file but before updating index. +connect(con1,localhost,root,,); +SET DEBUG_SYNC= "binlog_open_before_update_index SIGNAL con1_ready WAIT_FOR con1_cont"; +SET SESSION debug_dbug="+d,crash_create_critical_before_update_index"; +send INSERT INTO t1 VALUES (1, REPEAT("x", 4100)); + +connection default; +SET DEBUG_SYNC= "now WAIT_FOR con1_ready"; + +# Another connection creates a prepared transaction. +# After the transaction is prepared, it will hang waiting for LOCK_log. +connect(con2,localhost,root,,); +SET DEBUG_SYNC= "ha_commit_trans_after_prepare SIGNAL con2_ready"; +send INSERT INTO t1 VALUES (2, NULL); + +connection default; +SET DEBUG_SYNC= "now WAIT_FOR con2_ready"; + +# Now crash the server in con1, with old binlog closed, new binlog not yet in +# index, and one transaction in prepared-but-not-committed state. +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait-binlog_mdev342.test +EOF +# If con1 manages to race ahead and crash, we can see the crash already in the +# SET DEBUG_SYNC statement, so need --error here also. +--error 0,2006,2013 +SET DEBUG_SYNC= "now SIGNAL con1_cont"; +connection con1; +--error 2006,2013 +reap; + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart-binlog_mdev342.test +EOF + +connection default; +--enable_reconnect +--source include/wait_until_connected_again.inc + +# Check that all transactions are recovered. +SELECT a FROM t1 ORDER BY a; + +--source include/show_binary_logs.inc +--let $binlog_file= master-bin.000001 +--let $binlog_start= 4 +--source include/show_binlog_events.inc + +# Cleanup +connection default; +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/binlog_mdev717.test b/mysql-test/suite/binlog/t/binlog_mdev717.test new file mode 100644 index 00000000..61d3aa71 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mdev717.test @@ -0,0 +1,46 @@ +# MDEV-717 LP:1003679 - Wrong binlog order on concurrent DROP schema and CREATE function. + +--source include/have_debug_sync.inc +--source include/have_log_bin.inc +RESET MASTER; + +connect(con1,localhost,root); +connection default; + +CREATE DATABASE mysqltest; +SET DEBUG_SYNC= "after_wait_locked_schema_name SIGNAL locked WAIT_FOR release"; +--send DROP DATABASE mysqltest; +connection con1; +SET DEBUG_SYNC= "now WAIT_FOR locked"; +SET DEBUG_SYNC= "before_wait_locked_pname SIGNAL release"; +--error ER_BAD_DB_ERROR +CREATE FUNCTION mysqltest.f1() RETURNS INT RETURN 1; +connection default; +--reap + +CREATE DATABASE mysqltest; +SET DEBUG_SYNC= "after_wait_locked_schema_name SIGNAL locked WAIT_FOR release"; +--send DROP DATABASE mysqltest; +connection con1; +SET DEBUG_SYNC= "now WAIT_FOR locked"; +SET DEBUG_SYNC= "before_wait_locked_pname SIGNAL release"; +--error ER_BAD_DB_ERROR +CREATE EVENT mysqltest.e1 ON SCHEDULE EVERY 15 MINUTE DO BEGIN END; +connection default; +--reap + +CREATE DATABASE mysqltest; +CREATE EVENT mysqltest.e1 ON SCHEDULE EVERY 15 MINUTE DO BEGIN END; +SET DEBUG_SYNC= "after_wait_locked_schema_name SIGNAL locked WAIT_FOR release"; +--send DROP DATABASE mysqltest; +connection con1; +SET DEBUG_SYNC= "now WAIT_FOR locked"; +SET DEBUG_SYNC= "before_wait_locked_pname SIGNAL release"; +--error ER_BAD_DB_ERROR +ALTER EVENT mysqltest.e1 ON SCHEDULE EVERY 20 MINUTE DO BEGIN END; +connection default; +--reap + +SET DEBUG_SYNC= "RESET"; +--source include/show_binlog_events.inc + diff --git a/mysql-test/suite/binlog/t/binlog_mixed.test b/mysql-test/suite/binlog/t/binlog_mixed.test new file mode 100644 index 00000000..fa1b2ca3 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mixed.test @@ -0,0 +1,23 @@ +--source include/have_innodb.inc +--source include/have_binlog_format_mixed_or_row.inc + +# +# MDEV-22048 Assertion `binlog_table_maps == 0 || +# locked_tables_mode == LTM_LOCK_TABLES' failed in +# THD::reset_for_next_command +# + +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 (a) VALUES (1),(2); + +CREATE TABLE t2 (b INT) ENGINE=InnoDB; + +CREATE TRIGGER tr1 BEFORE UPDATE ON t1 FOR EACH ROW SET @a = 0; +CREATE TRIGGER tr2 BEFORE INSERT ON t2 FOR EACH ROW DELETE FROM t1 LIMIT 1; + +SET AUTOCOMMIT= OFF; +LOCK TABLES t2 WRITE; +DELETE FROM t1 LIMIT 1; +SAVEPOINT A; +UNLOCK TABLES; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/binlog/t/binlog_mixed_cache_stat.opt b/mysql-test/suite/binlog/t/binlog_mixed_cache_stat.opt new file mode 100644 index 00000000..2d4e658e --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mixed_cache_stat.opt @@ -0,0 +1 @@ +--binlog_cache_size=32768 --binlog_stmt_cache_size=32768 diff --git a/mysql-test/suite/binlog/t/binlog_mixed_cache_stat.test b/mysql-test/suite/binlog/t/binlog_mixed_cache_stat.test new file mode 100644 index 00000000..f22ea65d --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mixed_cache_stat.test @@ -0,0 +1,5 @@ +# This is a wrapper for binlog.test so that the same test case can be used +# For both statement and row based bin logs 9/19/2005 [jbm] + +-- source include/have_binlog_format_mixed.inc +-- source include/binlog_cache_stat.test diff --git a/mysql-test/suite/binlog/t/binlog_mixed_load_data.test b/mysql-test/suite/binlog/t/binlog_mixed_load_data.test new file mode 100644 index 00000000..7e7cb973 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mixed_load_data.test @@ -0,0 +1,15 @@ +# +# Bug #34283 mysqlbinlog leaves tmpfile after termination +# if binlog contains load data infile, so in mixed mode we +# go to row-based for avoiding the problem. +# + +--source include/have_binlog_format_mixed.inc +--source include/have_log_bin.inc + +RESET MASTER; +CREATE TABLE t1 (word CHAR(20) NOT NULL) ENGINE=MYISAM; +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1; +--source include/show_binlog_events.inc +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog-cp932-master.opt b/mysql-test/suite/binlog/t/binlog_mysqlbinlog-cp932-master.opt new file mode 100644 index 00000000..bb0cda45 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog-cp932-master.opt @@ -0,0 +1 @@ +--max-binlog-size=8192 diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog-cp932.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog-cp932.test new file mode 100644 index 00000000..80710261 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog-cp932.test @@ -0,0 +1 @@ +--source include/binlog_mysqlbinlog-cp932.inc diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog2-master.opt b/mysql-test/suite/binlog/t/binlog_mysqlbinlog2-master.opt new file mode 100644 index 00000000..4d69f335 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog2-master.opt @@ -0,0 +1 @@ +--timezone=GMT-3 diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog2.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog2.test new file mode 100644 index 00000000..53bf932e --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog2.test @@ -0,0 +1,217 @@ +# Test for the new options --start-datetime, stop-datetime, +# and a few others. + +# TODO: Need to look at making row based version once new binlog client is complete. +-- source include/have_binlog_format_mixed_or_statement.inc +-- source include/binlog_start_pos.inc + +set sql_mode=""; +set global binlog_checksum=NONE; +--disable_warnings +drop table if exists t1; +--enable_warnings + +# We need this for getting fixed timestamps inside of this test. +# I use a date in the past to keep a growing timestamp along the +# binlog (including the Start_log_event). This test will work +# unchanged everywhere, because mysql-test-run has fixed TZ, which it +# exports (so mysqlbinlog has same fixed TZ). +set @a=UNIX_TIMESTAMP("1970-01-21 15:32:22"); +set timestamp=@a; +reset master; +create table t1 (a int auto_increment not null primary key, b char(3)); +insert into t1 values(null, "a"); +insert into t1 values(null, "b"); +set timestamp=@a+2; +--let $binlog_pos_760=query_get_value(SHOW MASTER STATUS, Position, 1) +insert into t1 values(null, "c"); +--let $binlog_pos_951=query_get_value(SHOW BINLOG EVENTS in 'master-bin.000001' from $binlog_pos_760, Pos, 5) +set timestamp=@a+4; +insert into t1 values(null, "d"); +insert into t1 values(null, "e"); + +flush logs; +set timestamp=@a+1; # this could happen on a slave +insert into t1 values(null, "f"); +--let $binlog_pos_135=query_get_value(SHOW BINLOG EVENTS in 'master-bin.000002', Pos, 4) +--let $binlog_pos_203=query_get_value(SHOW BINLOG EVENTS in 'master-bin.000002', Pos, 5) + +# delimiters are for easier debugging in future + +--disable_query_log +select "--- Local --" as ""; +--enable_query_log + +# +# We should use --short-form everywhere because in other case output will +# be time dependent (the Start events). Better than nothing. +# +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form --base64-output=never $MYSQLD_DATADIR/master-bin.000001 + +--disable_query_log +select "--- offset --" as ""; +--enable_query_log +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form --offset=5 $MYSQLD_DATADIR/master-bin.000001 +--disable_query_log +select "--- start-position --" as ""; +--enable_query_log +let $start_pos= `select @binlog_start_pos + 705`; +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form --start-position=$start_pos $MYSQLD_DATADIR/master-bin.000001 +--disable_query_log +select "--- stop-position --" as ""; +--enable_query_log +let $stop_pos= `select @binlog_start_pos + 705`; +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form --stop-position=$stop_pos $MYSQLD_DATADIR/master-bin.000001 +--disable_query_log +select "--- start and stop positions ---" as ""; +--enable_query_log +let $start_pos= `select @binlog_start_pos + 705`; +let $stop_pos= `select @binlog_start_pos + 866`; +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form --start-position=$start_pos --stop-position=$stop_pos $MYSQLD_DATADIR/master-bin.000001 +--disable_query_log +select "--- start-datetime --" as ""; +--enable_query_log +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form "--start-datetime=1970-01-21 15:32:24" $MYSQLD_DATADIR/master-bin.000001 +--disable_query_log +select "--- stop-datetime --" as ""; +--enable_query_log +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form "--stop-datetime=1970-01-21 15:32:24" $MYSQLD_DATADIR/master-bin.000001 + +--disable_query_log +select "--- Local with 2 binlogs on command line --" as ""; +--enable_query_log + +# This is to verify that some options apply only to first, or last binlog + +flush logs; +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form $MYSQLD_DATADIR/master-bin.000001 $MYSQLD_DATADIR/master-bin.000002 + +--disable_query_log +select "--- offset --" as ""; +--enable_query_log +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form --offset=5 $MYSQLD_DATADIR/master-bin.000001 $MYSQLD_DATADIR/master-bin.000002 +--disable_query_log +select "--- start-position --" as ""; +--enable_query_log +let $start_pos= `select @binlog_start_pos + 705`; +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form --start-position=$start_pos $MYSQLD_DATADIR/master-bin.000001 $MYSQLD_DATADIR/master-bin.000002 +--disable_query_log +select "--- stop-position --" as ""; +--enable_query_log +let $stop_pos= `select @binlog_start_pos + 134`; +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form --stop-position=$stop_pos $MYSQLD_DATADIR/master-bin.000001 $MYSQLD_DATADIR/master-bin.000002 +--disable_query_log +select "--- start-datetime --" as ""; +--enable_query_log +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form "--start-datetime=1970-01-21 15:32:24" $MYSQLD_DATADIR/master-bin.000001 $MYSQLD_DATADIR/master-bin.000002 +--disable_query_log +select "--- stop-datetime --" as ""; +--enable_query_log +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form "--stop-datetime=1970-01-21 15:32:24" $MYSQLD_DATADIR/master-bin.000001 $MYSQLD_DATADIR/master-bin.000002 + +--disable_query_log +select "--- Remote --" as ""; +--enable_query_log + +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 + +--disable_query_log +select "--- offset --" as ""; +--enable_query_log +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form --offset=5 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 +--disable_query_log +select "--- start-position --" as ""; +--enable_query_log +let $start_pos= `select @binlog_start_pos + 705`; +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form --start-position=$start_pos --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 +--disable_query_log +select "--- stop-position --" as ""; +--enable_query_log +let $stop_pos= `select @binlog_start_pos + 705`; +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form --stop-position=$stop_pos --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 +--disable_query_log +select "--- start and stop positions ---" as ""; +--enable_query_log +let $start_pos= `select @binlog_start_pos + 705`; +let $stop_pos= `select @binlog_start_pos + 812`; +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form --start-position=$start_pos --stop-position $stop_pos --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 +--disable_query_log +select "--- start-datetime --" as ""; +--enable_query_log +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form "--start-datetime=1970-01-21 15:32:24" --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 +--disable_query_log +select "--- stop-datetime --" as ""; +--enable_query_log +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form "--stop-datetime=1970-01-21 15:32:24" --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 + +--disable_query_log +select "--- Remote with 2 binlogs on command line --" as ""; +--enable_query_log + +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002 + +--disable_query_log +select "--- offset --" as ""; +--enable_query_log +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form --offset=5 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002 +--disable_query_log +select "--- start-position --" as ""; +--enable_query_log +let $start_pos= `select @binlog_start_pos + 705`; +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form --start-position=$start_pos --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002 +--disable_query_log +select "--- stop-position --" as ""; +--enable_query_log +let $stop_pos= `select @binlog_start_pos + 109`; +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form --stop-position=$stop_pos --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002 +--disable_query_log +select "--- start-datetime --" as ""; +--enable_query_log +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form "--start-datetime=19700121153224" --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002 +--disable_query_log +select "--- stop-datetime --" as ""; +--enable_query_log +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form "--stop-datetime=1970/01/21 15@32@24" --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002 + +--disable_query_log +select "--- to-last-log --" as ""; +--enable_query_log + +--replace_regex /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ +--exec $MYSQL_BINLOG --short-form --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --to-last-log master-bin.000001 + +# clean up +--disable_query_log +select "--- end of test --" as ""; +--enable_query_log +drop table t1; + +set global binlog_checksum=default; +# End of 4.1 tests diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_base64.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_base64.test new file mode 100644 index 00000000..3d3444ce --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_base64.test @@ -0,0 +1,102 @@ +-- source include/have_binlog_format_row.inc +# +# Reset master to cleanup binlog +# +reset master; + +# +# Write different events to binlog +# +create table t1 (a int); +insert into t1 values (1); +insert into t1 values (2); +insert into t1 values (3); +update t1 set a=a+2 where a=2; +update t1 set a=a+2 where a=3; + +create table t2 (word varchar(20)); +load data infile '../../std_data/words.dat' into table t2; + +# +# Save binlog +# +let $MYSQLD_DATADIR=`select @@datadir`; +flush logs; +--exec $MYSQL_BINLOG --hexdump $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql + +# +# Clear database and restore from binlog +# +drop table t1; +drop table t2; +--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql + +# +# Verify that all binlog events have been executed +# +select * from t1; +select * from t2; + +# +# Verify that events larger than the default IO_CACHE buffer +# are handled correctly (BUG#25628). +# +flush logs; +drop table t2; +create table t2 (word varchar(20)); +load data infile '../../std_data/words.dat' into table t2; +insert into t2 select * from t2; +insert into t2 select * from t2; +insert into t2 select * from t2; +insert into t2 select * from t2; +insert into t2 select * from t2; +insert into t2 select * from t2; +insert into t2 select * from t2; +insert into t2 select * from t2; +insert into t2 select * from t2; +select count(*) from t2; + +flush logs; +--exec $MYSQL_BINLOG --hexdump $MYSQLD_DATADIR/master-bin.000003 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql +--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql + +# +# Verify that all binlog events have been executed +# +select count(*) from t2; + +# +# Test cleanup +# +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql +drop table t1; +drop table t2; + +# +# BUG#12354268 +# +# This test verifies that using --start-position with DECODE-ROWS +# does not make mysqlbinlog to output an error stating that it +# does not contain any FD event. +# + +RESET MASTER; +USE test; +SET @old_binlog_format= @@binlog_format; +SET SESSION binlog_format=ROW; +CREATE TABLE t1(c1 INT); +--let $master_binlog= query_get_value(SHOW MASTER STATUS, File, 1) +--let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1) +--let $MYSQLD_DATADIR= `SELECT @@datadir` + +INSERT INTO t1 VALUES (1); + +FLUSH LOGS; + +--disable_result_log +--exec $MYSQL_BINLOG --base64-output=DECODE-ROWS --start-position=$master_pos -v $MYSQLD_DATADIR/$master_binlog +--enable_result_log + +DROP TABLE t1; +SET SESSION binlog_format= @old_binlog_format; +RESET MASTER; diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_do_server_ids.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_do_server_ids.test new file mode 100644 index 00000000..9f32e2db --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_do_server_ids.test @@ -0,0 +1,477 @@ +# +# Purpose: +# +# This test validates that the option --do-server-ids for the mariadb-binlog +# command line tool correctly filters events by server id. +# +# +# Methodology: +# +# This test invokes mariadb-binlog using combinations of --do-server-ids with +# various combinations of other parameters to ensure it correctly filters by +# server id. Specifically, the following test cases are validated: +# Test Case 1) --do-server-ids with a single server id limits output to that +# single server +# Test Case 2) --do-server-ids with multiple server ids limits output to the +# provided servers +# Test Case 3) --do-server-ids when combined with --do-domain-ids should +# intersect the results +# Test Case 4) --do-server-ids when combined with --ignore-domain-ids should +# intersect the results +# Test Case 5) --do-server-ids when combined with a GTID range should +# intersect the results +# Test Case 6) --do-server-ids when combined with both --ignore-domain-ids +# and a GTID range should intersect all results +# Test Case 7) --do-server-ids when combined with both --do-domain-ids and +# a GTID range should intersect all results +# Test Case 8) --do-server-ids and --offset=<n> skips n events after the +# first GTID is found +# Test Case 9) --do-server-ids with --start-datetime=<T> where T occurs +# after the first GTID is found results in no events before T +# Test Case 10) --do-server-ids works with --read-from-remote-server +# Test Case 11) --do-server-ids works over multiple binary log input files +# Test Case 12) --do-server-ids re-specifications should override previous +# ones +# Test Case 13) --do-server-ids and --server-id should be aliases and a +# re-specification of one should override the former +# Test Case 14) --ignore-server-ids re-specifications should override +# previous ones +# Test Case 15) --do-domain-ids re-specifications should override previous +# ones +# Test Case 16) --ignore-domain-ids re-specifications should override +# previous ones +# +# Additionally, this test validates the following error scenarios: +# Error Case 1) --do-server-ids and --ignore-server-ids cannot be specified +# together +# Error Case 2) Invalid server ID number provided +# +# +# References: +# +# MDEV-20119: Implement the --do-domain-ids, --ignore-domain-ids, and +# --ignore-server-ids options for mysqlbinlog +# + +--source include/have_log_bin.inc + +--echo ############################### +--echo # Test Setup +--echo ############################### + + +# Save old state +let $ORIG_GTID_DOMAIN_ID = `select @@session.gtid_domain_id`; +let $ORIG_SERVER_ID = `select @@session.server_id`; + +# Configure test variables +--let $MYSQLD_DATADIR=`select @@datadir` + +--let table_inconsistent_err= "table data is inconsistent after replaying binlog events"; +--let table_exists_error= "table exists but binlog playback should have excluded its creation"; + +# Initialize test data +set @a=UNIX_TIMESTAMP("1970-01-21 15:32:22"); +SET timestamp=@a; +RESET MASTER; + +SET @@session.gtid_domain_id= 0; +SET @@session.server_id= 1; +CREATE TABLE t1 (a int); + +SET @@session.server_id= 2; +CREATE TABLE t2 (a int); +INSERT INTO t2 values (3); +--let t2_checksum= `CHECKSUM TABLE t2` + +SET @@session.gtid_domain_id= 1; +SET @@session.server_id= 1; +CREATE TABLE t3 (a int); +INSERT INTO t3 values (4); +--let t3_checksum= `CHECKSUM TABLE t3` + +SET @@session.server_id= 3; +SET timestamp=@a+1; +CREATE TABLE t4 (a int); +SET timestamp=@a+2; +INSERT INTO t4 values (5); +--let t4_checksum= `CHECKSUM TABLE t4` + +SET @@session.gtid_domain_id= 0; +SET @@session.server_id= 1; +INSERT INTO t1 values (1); +--let t1_partial_checksum= `CHECKSUM TABLE t1` + +SET @@session.gtid_domain_id= 2; +SET @@session.server_id= 1; +CREATE TABLE t5 (a int); +INSERT INTO t5 values (6); +--let t5_checksum= `CHECKSUM TABLE t5` + +SET @@session.gtid_domain_id= 0; +SET @@session.server_id= 1; +INSERT INTO t1 values (2); +--let t1_checksum= `CHECKSUM TABLE t1` + +FLUSH LOGS; + +SET @@session.gtid_domain_id= 0; +SET @@session.server_id= 2; +CREATE TABLE t6 (a int); +INSERT INTO t6 values (1); +--let t6_checksum= `CHECKSUM TABLE t6` +FLUSH LOGS; + +--let BINLOG_FILENAME= query_get_value(SHOW BINARY LOGS, Log_name, 1) +--let BINLOG_FILENAME2= query_get_value(SHOW BINARY LOGS, Log_name, 2) +--let BINLOG_FILE_PARAM= $MYSQLD_DATADIR/$BINLOG_FILENAME.orig +--let BINLOG_FILE_PARAM2= $MYSQLD_DATADIR/$BINLOG_FILENAME2.orig +--copy_file $MYSQLD_DATADIR/$BINLOG_FILENAME $BINLOG_FILE_PARAM +--copy_file $MYSQLD_DATADIR/$BINLOG_FILENAME2 $BINLOG_FILE_PARAM2 + +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP TABLE t4; +DROP TABLE t5; +DROP TABLE t6; +RESET MASTER; + +--echo ############################### +--echo # Test Cases +--echo ############################### + +--echo # +--echo # Test Case 1) --do-server-ids with a single server id limits output +--echo # to that single server +--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=2 | MYSQL +--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=2 | $MYSQL +if ($t2_checksum != `CHECKSUM TABLE t2`) +{ + die $table_inconsistent_err; +} +if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t3','t4','t5','t6')`) +{ + die $table_exists_error; +} +DROP TABLE t2; + + +--echo # +--echo # Test Case 2) --do-server-ids with multiple server ids limits output +--echo # to the provided servers +--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=2,3 | MYSQL +--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=2,3 | $MYSQL +if ($t2_checksum != `CHECKSUM TABLE t2`) +{ + die $table_inconsistent_err; +} +if ($t4_checksum != `CHECKSUM TABLE t4`) +{ + die $table_inconsistent_err; +} +if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t3','t5','t6')`) +{ + die $table_exists_error; +} +DROP TABLE t2; +DROP TABLE t4; + + +--echo # +--echo # Test Case 3) --do-server-ids when combined with --do-domain-ids should +--echo # intersect the results +--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=1 --do-domain-ids=0 | MYSQL +--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=1 --do-domain-ids=0 | $MYSQL +if ($t1_checksum != `CHECKSUM TABLE t1`) +{ + die $table_inconsistent_err; +} +if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t2','t3','t4','t5','t6')`) +{ + die $table_exists_error; +} +DROP TABLE t1; + + +--echo # +--echo # Test Case 4) --do-server-ids when combined with --ignore-domain-ids should +--echo # intersect the results +--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=1 --ignore-domain-ids=0 | MYSQL +--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=1 --ignore-domain-ids=0 | $MYSQL +if ($t3_checksum != `CHECKSUM TABLE t3`) +{ + die $table_inconsistent_err; +} +if ($t5_checksum != `CHECKSUM TABLE t5`) +{ + die $table_inconsistent_err; +} +if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t2','t4','t6')`) +{ + die $table_exists_error; +} +DROP TABLE t3; +DROP TABLE t5; + + +--echo # +--echo # Test Case 5) --do-server-ids when combined with a GTID range should +--echo # intersect the results +--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=1 --stop-position=0-1-4 | MYSQL +--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=1 --stop-position=0-1-4 | $MYSQL +if ($t1_partial_checksum != `CHECKSUM TABLE t1`) +{ + die $table_inconsistent_err; +} +if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t2','t3','t4','t5','t6')`) +{ + die $table_exists_error; +} +DROP TABLE t1; + + +--echo # +--echo # Test Case 6) --do-server-ids when combined with both --ignore-domain-ids +--echo # and a GTID range should intersect all results +--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=1 --ignore-domain-ids=0 --start-position=1-1-0 | MYSQL +--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=1 --ignore-domain-ids=0 --start-position=1-1-0 | $MYSQL +if ($t3_checksum != `CHECKSUM TABLE t3`) +{ + die $table_inconsistent_err; +} +if ($t5_checksum != `CHECKSUM TABLE t5`) +{ + die $table_inconsistent_err; +} +if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t2','t4','t6')`) +{ + die $table_exists_error; +} +DROP TABLE t3; +DROP TABLE t5; + + +--echo # +--echo # Test Case 7) --do-server-ids when combined with both --do-domain-ids and +--echo # a GTID range should intersect all results +--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=2 --do-domain-ids=0 --start-position=0-1-0 | MYSQL +--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=2 --do-domain-ids=0 --start-position=0-1-0 | $MYSQL +if ($t2_checksum != `CHECKSUM TABLE t2`) +{ + die $table_inconsistent_err; +} +if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t3','t4','t5','t6')`) +{ + die $table_exists_error; +} +DROP TABLE t2; + + + +--echo # +--echo # Test Case 8) --do-server-ids and --offset=<n> skips n events after the +--echo # first GTID is found + +# t4 needs to be specified because its creation should be skipped from +# --offset specification +CREATE TABLE t4 (a int); + +--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --offset=5 --do-server-ids=3 --do-domain-ids=1 | MYSQL +--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --offset=5 --do-server-ids=3 --do-domain-ids=1 | $MYSQL +if ($t4_checksum != `CHECKSUM TABLE t4`) +{ + die $table_inconsistent_err; +} +if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t2','t3','t5','t6')`) +{ + die $table_exists_error; +} +DROP TABLE t4; + + +--echo # +--echo # Test Case 9) --do-server-ids with --start-datetime=<T> where T occurs +--echo # after the first GTID is found results in no events before T + +# t4 needs to be specified because its creation should be skipped from +# --start-datetime specification +CREATE TABLE t4 (a int); + +--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --start-datetime="1970-01-21 15:32:24" --do-server-ids=3 --do-domain-ids=1 | MYSQL +--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --start-datetime="1970-01-21 15:32:24" --do-server-ids=3 --do-domain-ids=1 | $MYSQL +if ($t4_checksum != `CHECKSUM TABLE t4`) +{ + die $table_inconsistent_err; +} +if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t2','t3','t5','t6')`) +{ + die $table_exists_error; +} +DROP TABLE t4; + + +--echo # +--echo # Test Case 10) --do-server-ids works with --read-from-remote-server + +--echo # Setup test specific data +RESET MASTER; + +SET @@session.gtid_domain_id= 0; +SET @@session.server_id= 1; +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (1); + +SET @@session.server_id= 2; +CREATE TABLE t2 (a int); +INSERT INTO t2 VALUES (1); +--let t11_t2_checksum= `CHECKSUM TABLE t2` + +SET @@session.server_id= 1; +DROP TABLE t1; +DROP TABLE t2; + +--echo # MYSQL_BINLOG BINLOG_FILENAME --read-from-remote-server --do-server-ids=2 | MYSQL +--exec $MYSQL_BINLOG $BINLOG_FILENAME --read-from-remote-server --do-server-ids=2 | $MYSQL +if ($t11_t2_checksum != `CHECKSUM TABLE t2`) +{ + die $table_inconsistent_err; +} +if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t3','t4','t5','t6')`) +{ + die $table_exists_error; +} +DROP TABLE t2; + + +--echo # +--echo # Test Case 11) --do-server-ids works over multiple binary log input +--echo # files +--echo # MYSQL_BINLOG BINLOG_FILE_PARAM BINLOG_FILE_PARAM2 --do-server-ids=2 | MYSQL +--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM $BINLOG_FILE_PARAM2 --do-server-ids=2 | $MYSQL +if ($t2_checksum != `CHECKSUM TABLE t2`) +{ + die $table_inconsistent_err; +} +if ($t6_checksum != `CHECKSUM TABLE t6`) +{ + die $table_inconsistent_err; +} +if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t3','t4','t5')`) +{ + die $table_exists_error; +} +DROP TABLE t2; +DROP TABLE t6; + +--echo # +--echo # Test Case 12) --do-server-ids re-specifications should override +--echo # previous ones +--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=1 --do-server-ids=2 | MYSQL +--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=1 --do-server-ids=2 | $MYSQL +if ($t2_checksum != `CHECKSUM TABLE t2`) +{ + die $table_inconsistent_err; +} +if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t3','t4','t5','t6')`) +{ + die $table_exists_error; +} +DROP TABLE t2; + +--echo # +--echo # Test Case 13) --do-server-ids and --server-id should be aliases and +--echo # a re-specification of one should override the former +--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=1 --server-id=2 | MYSQL +--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=1 --server-id=2 | $MYSQL +if ($t2_checksum != `CHECKSUM TABLE t2`) +{ + die $table_inconsistent_err; +} +if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t3','t4','t5','t6')`) +{ + die $table_exists_error; +} +DROP TABLE t2; + +--echo # +--echo # Test Case 14) --ignore-server-ids re-specifications should override +--echo # previous ones +--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --ignore-server-ids=2 --ignore-server-ids=1,3 | MYSQL +--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --ignore-server-ids=2 --ignore-server-ids=1,3 | $MYSQL +if ($t2_checksum != `CHECKSUM TABLE t2`) +{ + die $table_inconsistent_err; +} +if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t1','t3','t4','t5','t6')`) +{ + die $table_exists_error; +} +DROP TABLE t2; + +--echo # +--echo # Test Case 15) --do-domain-ids re-specifications should override +--echo # previous ones +--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-domain-ids=1 --do-domain-ids=0 | MYSQL +--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-domain-ids=1 --do-domain-ids=0 | $MYSQL +if ($t1_checksum != `CHECKSUM TABLE t1`) +{ + die $table_inconsistent_err; +} +if ($t2_checksum != `CHECKSUM TABLE t2`) +{ + die $table_inconsistent_err; +} +if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t3','t4','t5','t6')`) +{ + die $table_exists_error; +} +DROP TABLE t1,t2; + +--echo # +--echo # Test Case 16) --ignore-domain-ids re-specifications should override +--echo # previous ones +--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --ignore-domain-ids=0 --ignore-domain-ids=1,2 | MYSQL +--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --ignore-domain-ids=0 --ignore-domain-ids=1,2 | $MYSQL +if ($t1_checksum != `CHECKSUM TABLE t1`) +{ + die $table_inconsistent_err; +} +if ($t2_checksum != `CHECKSUM TABLE t2`) +{ + die $table_inconsistent_err; +} +if (`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test' AND table_name IN ('t3','t4','t5','t6')`) +{ + die $table_exists_error; +} +DROP TABLE t1,t2; + +--echo ############################## +--echo # Error Cases +--echo ############################## + +--echo # +--echo # Error Case 1: +--echo # --ignore-server-ids and --do-server-ids both specified +--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=1 --ignore-server-ids=2 +--error 1 +--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=1 --ignore-server-ids=2 + +--echo # +--echo # Error Case 2: +--echo # Invalid server ID number provided +--echo # MYSQL_BINLOG BINLOG_FILE_PARAM --do-server-ids=-1 +--error 1 +--exec $MYSQL_BINLOG $BINLOG_FILE_PARAM --do-server-ids=-1 + +--echo ############################## +--echo # Cleanup +--echo ############################## +--eval SET @@global.gtid_domain_id= $ORIG_GTID_DOMAIN_ID +--eval SET @@global.server_id= $ORIG_SERVER_ID + +--remove_file $BINLOG_FILE_PARAM +--remove_file $BINLOG_FILE_PARAM2 + +--echo # End of tests diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_glle_ordered.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_glle_ordered.test new file mode 100644 index 00000000..9c79925b --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_glle_ordered.test @@ -0,0 +1,43 @@ +# +# Purpose: +# This test validates that GTIDs are ordered when mysqlbinlog outputs +# Gtid_list events. +# +# Methodology: +# Write multiple events to the binlog with different domain ids and server +# ids, and ensure that the Gtid_list event GTIDs are ordered first by domain id +# (ascending), and then sequence number (ascending). +# +# References: +# MDEV-4989: Support for GTID in mysqlbinlog +# +--source include/have_log_bin.inc + +RESET MASTER; +SET @@session.gtid_domain_id= 0; +SET @@session.server_id= 1; +CREATE TABLE t1 (a int); +SET @@session.gtid_domain_id= 1; +SET @@session.server_id= 2; +CREATE TABLE t2 (a int); +SET @@session.server_id= 1; +INSERT INTO t2 VALUES (1); +SET @@session.gtid_domain_id= 2; +SET @@session.server_id= 3; +CREATE TABLE t3 (a int); +FLUSH LOGS; +FLUSH LOGS; + +--let $binlog_file= query_get_value(SHOW BINARY LOGS, Log_name, 2) +--let $MYSQLD_DATADIR=`select @@datadir` +--let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/tmp_binlog.out + +--echo # MYSQL_BINLOG MYSQLD_DATADIR/binlog_file > SEARCH_FILE +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/$binlog_file > $SEARCH_FILE + +--let SEARCH_PATTERN= Gtid list \[0-1-1,\n# 1-2-1,\n# 1-1-2,\n# 2-3-1\] +--source include/search_pattern_in_file.inc + +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_gtid_strict_mode.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_gtid_strict_mode.test new file mode 100644 index 00000000..16682640 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_gtid_strict_mode.test @@ -0,0 +1,105 @@ +# +# Purpose: +# +# This test ensures that the mariadb-binlog CLI tool properly displays errors +# and warnings for out of order GTIDs. +# +# +# Methodology: +# +# We simulate invalid sequence numberings by manually changing gtid_seq_no to +# differ from its expected linear sequence. Specifically, we test the following +# cases: +# Test Case 1) Sequential sequence numbers results in no warnings +# Test Case 2) A skipped sequence number results in no warnings if all numbers +# are monotonic (i.e. gaps in sequence number are allowed +# provided they never decrease) +# Test Case 3) A sequence number lower than the last processed value results +# in a warning +# Test Case 4) Skipping a GTID and later receiving it results in a warning +# Test Case 5) Repeat sequence numbers result in a warning +# Test Case 6) Warnings from different domains are all displayed +# Test Case 7) A decreasing seq_no before a start-position is ignored +# Test Case 8) A decreasing seq_no inside of a --start/--stop position window +# is displayed +# Test Case 9) Error if --stop-position is not greater than or equal to +# --start-position +# Test Case 10) Strict mode warnings should be independent of --offset option +# specification +# Test Case 11) Strict mode warnings should be independent of +# --start-timestamp option specification +# Test Case 12) Specifying multiple binary logs with a log-position start +# should skip GTID state verification +# Test Case 13) If multiple binary logs should be specified but a middle log +# is missing, we should detect that and warn when using -vvv +# Test Case 14) If a --stop-position GTID occurs before the first specified +# binlog's GLLE, error +# +# Note that test cases are tested under three scenarios: +# 1) --gtid-strict-mode should error and immediately quit with error on out of +# order GTIDs +# 2) --skip-gtid-strict-mode -vvv should not quit early or with error when +# encountering out of order GTIDs; however should produce warnings after +# binlog processing +# 3) --skip-gtid-strict-mode should neither produce errors nor warnings when +# encountering out of order GTIDs +# +# References: +# MDEV-4989: Support for GTID in mysqlbinlog +# + +--source include/have_log_bin.inc + +--echo ############################### +--echo # Test Setup +--echo ############################### + +## Save old state +# +let orig_gtid_domain_id = `select @@session.gtid_domain_id`; +let orig_server_id = `select @@session.server_id`; +RESET MASTER; + +--echo #################################################### +--echo # Test Case Group 1 +--echo # +--echo # Tests with --gtid-strict-mode should error and +--echo # immediately quit with error on out of order GTIDs +--echo #################################################### +--let is_strict_mode= 1 +--let is_verbose= 0 +--let DEFAULT_ERROR_PREFIX=ERROR +--source include/mysqlbinlog_gtid_strict_mode.inc + +--echo #################################################### +--echo # Test Case Group 2 +--echo # +--echo # Test cases with --skip-gtid-strict-mode -vvv +--echo # should not quit early or with error when +--echo # encountering out of order GTIDs; however should +--echo # produce warnings after binlog processing +--echo #################################################### +--let is_strict_mode= 0 +--let is_verbose= 1 +--let DEFAULT_ERROR_PREFIX=WARNING +--source include/mysqlbinlog_gtid_strict_mode.inc + +--echo #################################################### +--echo # Test Case Group 3 +--echo # +--echo # Run test cases with --skip-gtid-strict-mode should +--echo # neither produce errors nor warnings when +--echo # encountering out of order GTIDs +--echo #################################################### +--let is_strict_mode= 0 +--let is_verbose= 0 +--let DEFAULT_ERROR_PREFIX=(ERROR|WARNING) +--source include/mysqlbinlog_gtid_strict_mode.inc + +--echo ############################## +--echo # Cleanup +--echo ############################## +--eval SET @@global.gtid_domain_id= $orig_gtid_domain_id +--eval SET @@global.server_id= $orig_server_id + +--echo End of the tests diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_gtid_window.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_gtid_window.test new file mode 100644 index 00000000..3efb8d02 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_gtid_window.test @@ -0,0 +1,151 @@ +# +# Purpose: +# +# This test ensures that the mariadb-binlog CLI tool can filter log events +# using GTID ranges. More specifically, this test ensures the following +# capabilities: +# 1) GTIDs can be used to filter results on local binlog files +# 2) GTIDs can be used to filter results from remote servers +# 3) For a given GTID range, its start-position is exclusive and its +# stop-position is inclusive. This allows users to receive events strictly +# after what they already have. +# 4) After the events have been written, the session server id and domain id +# are reset to their former values +# +# +# Methodology: +# +# This test validates the expected capabilities using the following test cases +# on both a local binlog file and remote server for all binlog formats. +# Test Case 1) The end of the binlog file resets the server and domain id of +# the session +# Test Case 2) Single GTID range specified +# Test Case 3) Single GTID range with different server_ids +# Test Case 4) Multiple GTID ranges specified +# Test Case 5) Multiple GTID ranges specified where the domain ids are +# listed in different orders between start/stop position +# Test Case 6) Only start position specified +# Test Case 7) Only stop position specified +# Test Case 8) Seq_no=0 in --start-position includes all events for a domain +# Test Case 9) Seq_no=0 in --stop-position excludes all events for a domain +# Test Case 10) Output stops for all domain ids when all --stop-position GTID +# values have been hit. +# Test Case 11) All GTID events from other domains are printed until +# the --stop-position values are hit +# Test Case 12) Scalar and GTID values can be used together for stop or start +# position +# Test Case 13) If the start position is delayed within the binlog, events +# occurring before that position are ignored +# Test Case 14) If start position is repeated, the last specification +# overrides all previous ones +# Test Case 15) If stop position is repeated, the last specification +# overrides all previous ones +# Test Case 16) Start position with --offset=<n> skips n events after the +# first GTID is found +# Test Case 17) Start position with --start-datetime=<T> where T occurs +# after the specified GTID results in no events before T +# Test Case 18) If --stop-position is specified, domains which are not present +# in its list should be excluded from output +# Test Case 19) If the start and stop GTIDs in any domain are equal, the +# domain should not have any output +# Test Case 20) If --start-position and --stop-position have different domain +# ids, only events from GTIDs in the --stop-position list are +# output +# Test Case 21) Successive binary logs (e.g. logs with previous logs that +# have been purged) will write events when the --start-position +# matches their Gtid_list_log_event state +# Test Case 22) Successive binary logs can be called with --stop-position and +# without --start-position +# +# To validate for data consistency, each test case compares a checksum of +# correct data against a variant created after replaying the binlog using +# --(start|stop)-position. If the checksums are identical, the test passes. +# If the checksums differ, data has been changed and the test fails. +# +# Additionally, this test validates the following error scenarios: +# Error Case 1) A GTID --start-position that does not mention all domains +# that make up the binary log state should error +# Error Case 2) A GTID --start-position with any sequence numbers which +# occur before the binary log state should result in error +# Error Case 3) A GTID --start-position with any sequence numbers that are not +# eventually processed results in error +# Error Case 4) User provides invalid positions +# Error Case 5) User provides GTID ranges with repeated domain ids +# +# References: +# MDEV-4989: Support for GTID in mysqlbinlog +# + +--source include/have_log_bin.inc + +--echo ############################### +--echo # Test Setup +--echo ############################### + +## Save old state +# +let orig_gtid_domain_id = `select @@session.gtid_domain_id`; +let orig_server_id = `select @@session.server_id`; +RESET MASTER; + + +--echo ###################################### +--echo # Test Group 1 +--echo # Run test cases on local log file +--echo ###################################### +--let is_remote= 0 +--source include/mysqlbinlog_gtid_window_test_cases.inc + +--echo ###################################### +--echo # Test Group 2 +--echo # Run test cases on remote host +--echo ###################################### +--let is_remote= 1 +--source include/mysqlbinlog_gtid_window_test_cases.inc + +# Note that error cases 1-3 are in mysqlbinlog_gtid_window_test_cases.inc +# because we validate for error consistency of GTID state between +# mariadb-binlog working on local files and receiving errors from a server + +--let err_out_= $MYSQLTEST_VARDIR/tmp/err.out +--let tmp_out_= $MYSQLTEST_VARDIR/tmp/std.out + +--let $MYSQLD_DATADIR=`select @@datadir` +--echo # +--echo # Error Case 4: +--echo # User provides invalid positions +--echo # MYSQL_BINLOG MYSQLD_DATADIR/master-bin.000001 --start-position=z +--error 1 +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 --start-position=z + +--echo # MYSQL_BINLOG MYSQLD_DATADIR/master-bin.000001 --start-position=1- +--error 1 +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 --start-position=1- + +--echo # MYSQL_BINLOG MYSQLD_DATADIR/master-bin.000001 --start-position=1-2 +--error 1 +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 --start-position=1-2 + +--echo # MYSQL_BINLOG MYSQLD_DATADIR/master-bin.000001 --start-position=1-2- +--error 1 +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 --start-position=1-2- + +--echo # MYSQL_BINLOG MYSQLD_DATADIR/master-bin.000001 --start-position=-1 +--error 1 +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 --start-position=-1 + +--echo # +--echo # Error Case 5: +--echo # User provides GTID ranges with repeated domain ids +--echo # MYSQL_BINLOG MYSQLD_DATADIR/master-bin.000001 --start-position=0-1-1,0-1-8 --stop-position=0-1-4,0-1-12 +--error 1 +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 --start-position=0-1-1,0-1-8 --stop-position=0-1-4,0-1-12 + + +--echo ############################## +--echo # Cleanup +--echo ############################## +--eval SET @@global.gtid_domain_id= $orig_gtid_domain_id +--eval SET @@global.server_id= $orig_server_id + +--echo # End of the tests diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_raw_flush.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_raw_flush.test new file mode 100644 index 00000000..252a8577 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_raw_flush.test @@ -0,0 +1,54 @@ +# +# Purpose: +# When using mariadb-binlog with options for --raw and --stop-never, events +# from the master's currently active log file should be written to their +# respective log file specified by --result-file, and shown on-disk. This test +# ensures that the log files on disk, created by mariadb-binlog, have the most +# up-to-date events from the master. +# Option --raw works only with --read-from-remote-server, otherwise returns error. +# +# Methodology: +# On the master, rotate to a newly active binlog file and write an event to +# it. Read the master's binlog using mariadb-binlog with --raw and --stop-never +# and write the data to an intermediary binlog file (a timeout is used on this +# command to ensure it exits). Read the local intermediary binlog file to ensure +# that the master's most recent event exists in the local file. +# +# References: +# MDEV-14608: mysqlbinlog lastest backupfile size is 0 +# + +--source include/linux.inc +--source include/have_log_bin.inc + +--echo # +--echo # MDEV-30698 Cover missing test cases for mariadb-binlog options +--echo # --raw [and] --flashback +--echo # +# Test --raw format without -R (--read-from-remote-server) +--error 1 # Error 1 operation not permitted +--exec $MYSQL_BINLOG --raw --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --stop-never --result-file=$MYSQLTEST_VARDIR/tmp/ master-bin.000001 + +# Create newly active log +CREATE TABLE t1 (a int); +FLUSH LOGS; +INSERT INTO t1 VALUES (1); + +# Read binlog data from master to intermediary result file +--let TIMEOUT=1 +--echo # timeout TIMEOUT MYSQL_BINLOG --raw --read-from-remote-server --user=root --host=127.0.0.1 --port=MASTER_MYPORT --stop-never --result-file=MYSQLTEST_VARDIR/tmp/ master-bin.000001 +--error 124 # Error 124 means timeout was reached +--exec timeout $TIMEOUT $MYSQL_BINLOG --raw --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --stop-never --result-file=$MYSQLTEST_VARDIR/tmp/ master-bin.000001 + +# Ensure the binlog output has the most recent events from the master +--echo # MYSQL_BINLOG MYSQLTEST_VARDIR/tmp/master-bin.000002 > MYSQLTEST_VARDIR/tmp/local-bin.000002.out +--exec $MYSQL_BINLOG $MYSQLTEST_VARDIR/tmp/master-bin.000002 > $MYSQLTEST_VARDIR/tmp/local-bin.000002.out +--let SEARCH_PATTERN= GTID 0-1-2 +--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/local-bin.000002.out +--source include/search_pattern_in_file.inc + +# Cleanup +DROP TABLE t1; +--remove_file $MYSQLTEST_VARDIR/tmp/master-bin.000001 +--remove_file $MYSQLTEST_VARDIR/tmp/master-bin.000002 +--remove_file $MYSQLTEST_VARDIR/tmp/local-bin.000002.out diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row-master.opt b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row-master.opt new file mode 100644 index 00000000..4d69f335 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row-master.opt @@ -0,0 +1 @@ +--timezone=GMT-3 diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row.test new file mode 100644 index 00000000..113e4ed7 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row.test @@ -0,0 +1,491 @@ +--source include/have_log_bin.inc +--source include/have_binlog_format_row.inc +--source include/have_ucs2.inc + +--echo # +--echo # Preparatory cleanup. +--echo # +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +--echo # +--echo # We need a fixed timestamp to avoid varying results. +--echo # +SET timestamp=1000000000; + +--echo # +--echo # Delete all existing binary logs. +--echo # +RESET MASTER; + + +CREATE TABLE t1 (c01 BIT); +INSERT INTO t1 VALUES (0); +INSERT INTO t1 VALUES (1); +DROP TABLE t1; + +CREATE TABLE t1 (c01 BIT(7)); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (16); +INSERT INTO t1 VALUES (32); +INSERT INTO t1 VALUES (64); +INSERT INTO t1 VALUES (127); +DELETE FROM t1 WHERE c01=127; +UPDATE t1 SET c01=15 WHERE c01=16; +DROP TABLE t1; + +CREATE TABLE t1 (a BIT(20), b CHAR(2)); +INSERT INTO t1 VALUES (b'00010010010010001001', 'ab'); +DROP TABLE t1; + +CREATE TABLE t1 (c02 BIT(64)); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (128); +INSERT INTO t1 VALUES (b'1111111111111111111111111111111111111111111111111111111111111111'); +DROP TABLE t1; + + +CREATE TABLE t1 (c03 TINYINT); +INSERT INTO t1 VALUES (1),(2),(3); +INSERT INTO t1 VALUES (-128); +UPDATE t1 SET c03=2 WHERE c03=1; +DELETE FROM t1 WHERE c03=-128; +DROP TABLE t1; + +CREATE TABLE t1 (c04 TINYINT UNSIGNED); +INSERT INTO t1 VALUES (128), (255); +UPDATE t1 SET c04=2 WHERE c04=1; +DELETE FROM t1 WHERE c04=255; +DROP TABLE t1; + +CREATE TABLE t1 (c06 BOOL); +INSERT INTO t1 VALUES (TRUE); +DELETE FROM t1 WHERE c06=TRUE; +DROP TABLE t1; + +CREATE TABLE t1 (c07 SMALLINT); +INSERT INTO t1 VALUES (1234); +DELETE FROM t1 WHERE c07=1234; +DROP TABLE t1; + +CREATE TABLE t1 (c08 SMALLINT UNSIGNED); +INSERT INTO t1 VALUES (32768), (65535); +UPDATE t1 SET c08=2 WHERE c08=32768; +DELETE FROM t1 WHERE c08=65535; +DROP TABLE t1; + +CREATE TABLE t1 (c10 MEDIUMINT); +INSERT INTO t1 VALUES (12345); +DELETE FROM t1 WHERE c10=12345; +DROP TABLE t1; + +CREATE TABLE t1 (c11 MEDIUMINT UNSIGNED); +INSERT INTO t1 VALUES (8388608), (16777215); +UPDATE t1 SET c11=2 WHERE c11=8388608; +DELETE FROM t1 WHERE c11=16777215; +DROP TABLE t1; + +CREATE TABLE t1 (c13 INT); +INSERT INTO t1 VALUES (123456); +DELETE FROM t1 WHERE c13=123456; +DROP TABLE t1; + +CREATE TABLE t1 (c14 INT UNSIGNED); +INSERT INTO t1 VALUES (2147483648), (4294967295); +UPDATE t1 SET c14=2 WHERE c14=2147483648; +DELETE FROM t1 WHERE c14=4294967295; +DROP TABLE t1; + +CREATE TABLE t1 (c16 BIGINT); +INSERT INTO t1 VALUES (1234567890); +DELETE FROM t1 WHERE c16=1234567890; +DROP TABLE t1; + +CREATE TABLE t1 (c17 BIGINT UNSIGNED); +INSERT INTO t1 VALUES (9223372036854775808), (18446744073709551615); +UPDATE t1 SET c17=2 WHERE c17=9223372036854775808; +DELETE FROM t1 WHERE c17=18446744073709551615; +DROP TABLE t1; + +CREATE TABLE t1 (c19 FLOAT); +INSERT INTO t1 VALUES (123.2234); +DELETE FROM t1 WHERE c19>123; +DROP TABLE t1; + +CREATE TABLE t1 (c22 DOUBLE); +INSERT INTO t1 VALUES (123434.22344545); +DELETE FROM t1 WHERE c22>123434; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c25 DECIMAL(10,5)); +INSERT INTO t1 VALUES (124.45); +INSERT INTO t1 VALUES (-543.21); +DELETE FROM t1 WHERE c25=124.45; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c28 DATE); +INSERT INTO t1 VALUES ('2001-02-03'); +DELETE FROM t1 WHERE c28='2001-02-03'; +DROP TABLE t1; + +CREATE TABLE t1 (c29 DATETIME); +INSERT INTO t1 VALUES ('2001-02-03 10:20:30'); +DELETE FROM t1 WHERE c29='2001-02-03 10:20:30'; +DROP TABLE t1; + +CREATE TABLE t1 (c30 TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP); +INSERT INTO t1 VALUES ('2001-02-03 10:20:30'); +DELETE FROM t1 WHERE c30='2001-02-03 10:20:30'; +DROP TABLE t1; + +CREATE TABLE t1 (c31 TIME); +INSERT INTO t1 VALUES ('11:22:33'); +DELETE FROM t1 WHERE c31='11:22:33'; +DROP TABLE t1; + +CREATE TABLE t1 (c32 YEAR); +INSERT INTO t1 VALUES ('2001'); +DELETE FROM t1 WHERE c32=2001; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c33 CHAR); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c33='a'; +DROP TABLE t1; + +CREATE TABLE t1 (c34 CHAR(0)); +INSERT INTO t1 VALUES (''); +DELETE FROM t1 WHERE c34=''; +DROP TABLE t1; + +CREATE TABLE t1 (c35 CHAR(1)); +INSERT INTO t1 VALUES ('b'); +DELETE FROM t1 WHERE c35='b'; +DROP TABLE t1; + +CREATE TABLE t1 (c36 CHAR(255)); +INSERT INTO t1 VALUES (repeat('c',255)); +DELETE FROM t1 WHERE c36>'c'; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c37 NATIONAL CHAR); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c37='a'; +DROP TABLE t1; + +CREATE TABLE t1 (c38 NATIONAL CHAR(0)); +INSERT INTO t1 VALUES (''); +DELETE FROM t1 WHERE c38=''; +DROP TABLE t1; + +CREATE TABLE t1 (c39 NATIONAL CHAR(1)); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c39='a'; +DROP TABLE t1; + +CREATE TABLE t1 (c40 NATIONAL CHAR(255)); +INSERT INTO t1 VALUES (repeat('a', 255)); +INSERT INTO t1 VALUES (repeat(_latin1 0xDF, 255)); +DELETE FROM t1 WHERE c40>'a'; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c41 CHAR CHARACTER SET UCS2); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c41='a'; +DROP TABLE t1; + +CREATE TABLE t1 (c42 CHAR(0) CHARACTER SET UCS2); +INSERT INTO t1 VALUES (''); +DELETE FROM t1 WHERE c42=''; +DROP TABLE t1; + +CREATE TABLE t1 (c43 CHAR(1) CHARACTER SET UCS2); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c43='a'; +DROP TABLE t1; + +CREATE TABLE t1 (c44 CHAR(255) CHARACTER SET UCS2); +INSERT INTO t1 VALUES (repeat('a', 255)); +INSERT INTO t1 VALUES (repeat(_latin1 0xDF, 255)); +DELETE FROM t1 WHERE c44>'a'; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c45 VARCHAR(0)); +INSERT INTO t1 VALUES (''); +DELETE FROM t1 WHERE c45=''; +DROP TABLE t1; + +CREATE TABLE t1 (c46 VARCHAR(1)); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c46='a'; +DROP TABLE t1; + +CREATE TABLE t1 (c47 VARCHAR(255)); +INSERT INTO t1 VALUES (repeat('a',255)); +DELETE FROM t1 WHERE c47>'a'; +DROP TABLE t1; + +CREATE TABLE t1 (c48 VARCHAR(261)); +INSERT INTO t1 VALUES (repeat('a',261)); +DELETE FROM t1 WHERE c48>'a'; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c49 NATIONAL VARCHAR(0)); +INSERT INTO t1 VALUES (''); +DELETE FROM t1 WHERE c49=''; +DROP TABLE t1; + +CREATE TABLE t1 (c50 NATIONAL VARCHAR(1)); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c50='a'; +DROP TABLE t1; + +CREATE TABLE t1 (c51 NATIONAL VARCHAR(255)); +INSERT INTO t1 VALUES (repeat('a',255)); +INSERT INTO t1 VALUES (repeat(_latin1 0xDF, 255)); +DELETE FROM t1 WHERE c51>'a'; +DROP TABLE t1; + +CREATE TABLE t1 (c52 NATIONAL VARCHAR(261)); +INSERT INTO t1 VALUES (repeat('a',261)); +INSERT INTO t1 VALUES (repeat(_latin1 0xDF, 261)); +DELETE FROM t1 WHERE c52>'a'; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c53 VARCHAR(0) CHARACTER SET ucs2); +INSERT INTO t1 VALUES (''); +DELETE FROM t1 WHERE c53=''; +DROP TABLE t1; + +CREATE TABLE t1 (c54 VARCHAR(1) CHARACTER SET ucs2); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c54='a'; +DROP TABLE t1; + +CREATE TABLE t1 (c55 VARCHAR(255) CHARACTER SET ucs2); +INSERT INTO t1 VALUES (repeat('ab', 127)); +DELETE FROM t1 WHERE c55>'a'; +DROP TABLE t1; + +CREATE TABLE t1 (c56 VARCHAR(261) CHARACTER SET ucs2); +INSERT INTO t1 VALUES (repeat('ab', 130)); +DELETE FROM t1 WHERE c56>'a'; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c57 BINARY); +INSERT INTO t1 VALUES (0x00); +INSERT INTO t1 VALUES (0x02); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c57='a'; +DROP TABLE t1; + +CREATE TABLE t1 (c58 BINARY(0)); +INSERT INTO t1 VALUES (''); +DELETE FROM t1 WHERE c58=''; +DROP TABLE t1; + +CREATE TABLE t1 (c59 BINARY(1)); +INSERT INTO t1 VALUES (0x00); +INSERT INTO t1 VALUES (0x02); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c59='a'; +DROP TABLE t1; + +CREATE TABLE t1 (c60 BINARY(255)); +INSERT INTO t1 VALUES (0x00); +INSERT INTO t1 VALUES (0x02); +INSERT INTO t1 VALUES (repeat('a\0',120)); +DELETE FROM t1 WHERE c60<0x02; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c61 VARBINARY(0)); +INSERT INTO t1 VALUES (''); +DELETE FROM t1 WHERE c61=''; +DROP TABLE t1; + +CREATE TABLE t1 (c62 VARBINARY(1)); +INSERT INTO t1 VALUES (0x00); +INSERT INTO t1 VALUES (0x02); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c62=0x02; +DROP TABLE t1; + +CREATE TABLE t1 (c63 VARBINARY(255)); +INSERT INTO t1 VALUES (0x00); +INSERT INTO t1 VALUES (0x02); +INSERT INTO t1 VALUES (repeat('a\0',120)); +DELETE FROM t1 WHERE c63=0x02; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c65 TINYBLOB); +INSERT INTO t1 VALUES ('tinyblob1'); +DELETE FROM t1 WHERE c65='tinyblob1'; +DROP TABLE t1; + +CREATE TABLE t1 (c68 BLOB); +INSERT INTO t1 VALUES ('blob1'); +DELETE FROM t1 WHERE c68='blob1'; +DROP TABLE t1; + +CREATE TABLE t1 (c71 MEDIUMBLOB); +INSERT INTO t1 VALUES ('mediumblob1'); +DELETE FROM t1 WHERE c71='mediumblob1'; +DROP TABLE t1; + +CREATE TABLE t1 (c74 LONGBLOB); +INSERT INTO t1 VALUES ('longblob1'); +DELETE FROM t1 WHERE c74='longblob1'; +DROP TABLE t1; + +CREATE TABLE t1 (c66 TINYTEXT); +INSERT INTO t1 VALUES ('tinytext1'); +DELETE FROM t1 WHERE c66='tinytext1'; +DROP TABLE t1; + +CREATE TABLE t1 (c69 TEXT); +INSERT INTO t1 VALUES ('text1'); +DELETE FROM t1 WHERE c69='text1'; +DROP TABLE t1; + +CREATE TABLE t1 (c72 MEDIUMTEXT); +INSERT INTO t1 VALUES ('mediumtext1'); +DELETE FROM t1 WHERE c72='mediumtext1'; +DROP TABLE t1; + +CREATE TABLE t1 (c75 LONGTEXT); +INSERT INTO t1 VALUES ('longtext1'); +DELETE FROM t1 WHERE c75='longtext1'; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c67 TINYTEXT CHARACTER SET UCS2); +INSERT INTO t1 VALUES ('tinytext1'); +DELETE FROM t1 WHERE c67='tinytext1'; +DROP TABLE t1; + +CREATE TABLE t1 (c70 TEXT CHARACTER SET UCS2); +INSERT INTO t1 VALUES ('text1'); +DELETE FROM t1 WHERE c70='text1'; +DROP TABLE t1; + +CREATE TABLE t1 (c73 MEDIUMTEXT CHARACTER SET UCS2); +INSERT INTO t1 VALUES ('mediumtext1'); +DELETE FROM t1 WHERE c73='mediumtext1'; +DROP TABLE t1; + +CREATE TABLE t1 (c76 LONGTEXT CHARACTER SET UCS2); +INSERT INTO t1 VALUES ('longtext1'); +DELETE FROM t1 WHERE c76='longtext1'; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c77 ENUM('a','b','c')); +INSERT INTO t1 VALUES ('b'); +DELETE FROM t1 WHERE c77='b'; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c78 SET('a','b','c','d','e','f')); +INSERT INTO t1 VALUES ('a,b'); +INSERT INTO t1 VALUES ('a,c'); +INSERT INTO t1 VALUES ('b,c'); +INSERT INTO t1 VALUES ('a,b,c'); +INSERT INTO t1 VALUES ('a,b,c,d'); +INSERT INTO t1 VALUES ('a,b,c,d,e'); +INSERT INTO t1 VALUES ('a,b,c,d,e,f'); +DELETE FROM t1 WHERE c78='a,b'; +DROP TABLE t1; + +# +# Check multi-table update +# +CREATE TABLE t1 (a int NOT NULL DEFAULT 0, b int NOT NULL DEFAULT 0); +CREATE TABLE t2 (a int NOT NULL DEFAULT 0, b int NOT NULL DEFAULT 0); +INSERT INTO t1 SET a=1; +INSERT INTO t1 SET b=1; +INSERT INTO t2 SET a=1; +INSERT INTO t2 SET b=1; +UPDATE t1, t2 SET t1.a=10, t2.a=20; +DROP TABLE t1,t2; + +--echo # +--echo # MDEV-20591 Wrong Number of rows in mysqlbinlog output. +--echo # + +CREATE TABLE t1(c_char_utf8 CHAR(10) , + c_varchar_utf8 char(10) , + c_text_utf8 blob ); + +INSERT into t1 values("B", "B", REPEAT("#", 2000)); + +drop table t1; + +flush logs; + +let $MYSQLD_DATADIR= `select @@datadir`; + +--copy_file std_data/old_decimal/t1dec102.frm $MYSQLD_DATADIR/test/t1dec102.frm +--copy_file std_data/old_decimal/t1dec102.MYD $MYSQLD_DATADIR/test/t1dec102.MYD +--copy_file std_data/old_decimal/t1dec102.MYI $MYSQLD_DATADIR/test/t1dec102.MYI + +INSERT INTO t1dec102 VALUES (-999.99); +INSERT INTO t1dec102 VALUES (0); +INSERT INTO t1dec102 VALUES (999.99); +SELECT * FROM t1dec102 ORDER BY a; +DROP TABLE t1dec102; + +flush logs; +# +# MDEV-22330: mysqlbinlog stops with an error Don't know how to handle column +# type: 255 meta: 4 (0004) +# Check support for GEOMETRY type with verbose mode. +# +CREATE TABLE t1 (a GEOMETRY DEFAULT NULL); + +INSERT INTO t1 VALUES (NULL); +INSERT INTO t1 VALUES (POINT(10,10)); +DROP TABLE t1; +FLUSH LOGS; + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /server v [^ ]*/server v #.##.##/ /(@[0-9]*=[0-9]*[.][0-9]{1,3})[0-9e+-]*[^ ]*(.*(FLOAT|DOUBLE).*[*].)/\1...\2/ /CRC32 0x[0-9a-f]*/CRC32 XXX/ /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ /xid=\d*/xid=<xid>/ +--exec $MYSQL_BINLOG --base64-output=decode-rows -v -v $MYSQLD_DATADIR/master-bin.000001 + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /server v [^ ]*/server v #.##.##/ /(@[0-9]*=[0-9]*[.][0-9]{1,3})[0-9e+-]*[^ ]*(.*(FLOAT|DOUBLE).*[*].)/\1...\2/ /CRC32 0x[0-9a-f]*/CRC32 XXX/ /xid=\d*/xid=<xid>/ +--error 1 +--exec $MYSQL_BINLOG --base64-output=decode-rows -v -v $MYSQLD_DATADIR/master-bin.000002 2>&1 + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /server v [^ ]*/server v #.##.##/ /(@[0-9]*=[0-9]*[.][0-9]{1,3})[0-9e+-]*[^ ]*(.*(FLOAT|DOUBLE).*[*].)/\1...\2/ /CRC32 0x[0-9a-f]*/CRC32 XXX/ /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ /xid=\d*/xid=<xid>/ +--exec $MYSQL_BINLOG --base64-output=decode-rows -v -v $MYSQLD_DATADIR/master-bin.000003 diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_frag.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_frag.test new file mode 100644 index 00000000..3e18ef1e --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_frag.test @@ -0,0 +1,50 @@ +--source include/have_debug.inc +--source include/have_binlog_format_row.inc + +--let $MYSQLD_DATADIR= `select @@datadir` + +CREATE TABLE t (a TEXT); +# events of interest are guaranteed to stay in 000001 log +RESET MASTER; +--eval INSERT INTO t SET a=repeat('a', 1024) +SELECT a into @a from t; +FLUSH LOGS; +DELETE FROM t; + +--exec $MYSQL_BINLOG --verbose --debug-binlog-row-event-max-encoded-size=256 $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql + +--let SEARCH_PATTERN= BINLOG @binlog_fragment_0, @binlog_fragment_1 +--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql +--source include/search_pattern_in_file.inc + +--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql + +SELECT a LIKE @a as 'true' FROM t; + +# improper syntax error +--echo BINLOG number-of-fragments must be exactly two +--error ER_PARSE_ERROR +BINLOG @binlog_fragment; +--error ER_PARSE_ERROR +BINLOG @binlog_fragment, @binlog_fragment, @binlog_fragment; + +# corrupted fragments error check (to the expected error code notice, +# the same error code occurs in a similar unfragmented case) +SET @binlog_fragment_0='012345'; +SET @binlog_fragment_1='012345'; +--error ER_SYNTAX_ERROR +BINLOG @binlog_fragment_0, @binlog_fragment_1; + +# Not existing fragment is not allowed +SET @binlog_fragment_0='012345'; +--error ER_WRONG_TYPE_FOR_VAR +BINLOG @binlog_fragment_0, @binlog_fragment_not_exist; + +# MDEV-22520 +SET @a= '42'; +--error ER_SYNTAX_ERROR +BINLOG @a, @a; + +--echo # Cleanup +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql +DROP TABLE t; diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_innodb-master.opt b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_innodb-master.opt new file mode 100644 index 00000000..4d69f335 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_innodb-master.opt @@ -0,0 +1 @@ +--timezone=GMT-3 diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_innodb.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_innodb.test new file mode 100644 index 00000000..7bd72657 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_innodb.test @@ -0,0 +1,28 @@ +# mysqlbinlog_row_innodb.test +# +# Show that mysqlbinlog displays human readable comments to +# row-based log events. +# +# Main module for the InnoDB storage engine. +# +# Calls include/mysqlbinlog_row.inc +# See there for more informaton. +# + +--source include/have_innodb.inc +let $engine_type=InnoDB; + +SET @save_stats_auto_recalc=@@GLOBAL.innodb_stats_auto_recalc; +SET GLOBAL innodb_stats_auto_recalc=OFF; + +# +# The test case would also work with statement based or mixed mode logging. +# But this would require different result files. To handle this with the +# current test suite, new main test cases are required. +# +--source include/have_binlog_format_row.inc +--source include/have_ucs2.inc + +--source include/mysqlbinlog_row_engine.inc + +SET GLOBAL innodb_stats_auto_recalc=@save_stats_auto_recalc; diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_myisam-master.opt b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_myisam-master.opt new file mode 100644 index 00000000..4d69f335 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_myisam-master.opt @@ -0,0 +1 @@ +--timezone=GMT-3 diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_myisam.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_myisam.test new file mode 100644 index 00000000..e7b03358 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_myisam.test @@ -0,0 +1,23 @@ +# mysqlbinlog_row.test +# +# Show that mysqlbinlog displays human readable comments to +# row-based log events. +# +# Main module for the MyISAM storage engine. +# +# Calls include/mysqlbinlog_row.inc +# See there for more informaton. +# + +#--source include/have_myisam.inc +let $engine_type=MyISAM; + +# +# The test case would also work with statement based or mixed mode logging. +# But this would require different result files. To handle this with the +# current test suite, new main test cases are required. +# +--source include/have_binlog_format_row.inc +--source include/have_ucs2.inc + +--source include/mysqlbinlog_row_engine.inc diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_trans-master.opt b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_trans-master.opt new file mode 100644 index 00000000..4d69f335 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_trans-master.opt @@ -0,0 +1 @@ +--timezone=GMT-3 diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_trans.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_trans.test new file mode 100644 index 00000000..3b054884 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_trans.test @@ -0,0 +1,159 @@ +# mysqlbinlog_trans.test +# +# Show that mysqlbinlog work correctly with transactions. +# + +#--source include/have_myisam.inc +--let $engine_type_nontrans= MyISAM +--source include/have_innodb.inc +--let $engine_type= InnoDB + +# +# The test case would also work with statement based or mixed mode logging. +# But this would require different result files. To handle this with the +# current test suite, new main test cases are required. +# +--source include/have_binlog_format_row.inc + +--source include/have_log_bin.inc + +--echo # +--echo # Preparatory cleanup. +--echo # +--disable_warnings +DROP TABLE IF EXISTS t1, t2; +--enable_warnings + +--echo # +--echo # We need a fixed timestamp to avoid varying results. +--echo # +SET timestamp=1000000000; + +--echo # +--echo # Delete all existing binary logs. +--echo # +RESET MASTER; + +--echo # +--echo # Create test tables. +--echo # +eval CREATE TABLE t1 ( + c1 INT, + c2 VARCHAR(20) + ) ENGINE=$engine_type DEFAULT CHARSET latin1; +eval CREATE TABLE t2 ( + c1 INT, + c2 VARCHAR(20) + ) ENGINE=$engine_type_nontrans DEFAULT CHARSET latin1; + +--echo # +--echo # Start transaction #1, transactional table only, commit. +--echo # +START TRANSACTION; + +--echo # +--echo # Do some statements. +--echo # +INSERT INTO t1 VALUES (1,'varchar-1'), (2,'varchar-2'), (3,'varchar-3'); +UPDATE t1 SET c1 = c1 + 10; +DELETE FROM t1 WHERE c1 = 12; + +--echo # +--echo # Commit transaction. +--echo # +COMMIT; +SELECT * FROM t1; +TRUNCATE TABLE t1; + +--echo # +--echo # Start transaction #2, transactional table only, rollback. +--echo # +START TRANSACTION; + +--echo # +--echo # Do some statements. +--echo # +INSERT INTO t1 VALUES (1,'varchar-1'), (2,'varchar-2'), (3,'varchar-3'); +UPDATE t1 SET c1 = c1 + 10; +DELETE FROM t1 WHERE c1 = 12; + +--echo # +--echo # Rollback transaction. +--echo # +ROLLBACK; +SELECT * FROM t1; +TRUNCATE TABLE t1; + +--echo # +--echo # Start transaction #3, both tables, commit. +--echo # +START TRANSACTION; + +--echo # +--echo # Do some statements on the transactional table. +--echo # +INSERT INTO t1 VALUES (1,'varchar-1'), (2,'varchar-2'), (3,'varchar-3'); +UPDATE t1 SET c1 = c1 + 10; +DELETE FROM t1 WHERE c1 = 12; + +--echo # +--echo # Do some statements on the non-transactional table. +--echo # +INSERT INTO t2 VALUES (1,'varchar-1'), (2,'varchar-2'), (3,'varchar-3'); +UPDATE t2 SET c1 = c1 + 10; +DELETE FROM t2 WHERE c1 = 12; + +--echo # +--echo # Commit transaction. +--echo # +COMMIT; +SELECT * FROM t1; +SELECT * FROM t2; +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; + +--echo # +--echo # Start transaction #4, both tables, rollback. +--echo # +START TRANSACTION; + +--echo # +--echo # Do some statements on the transactional table. +--echo # +INSERT INTO t1 VALUES (1,'varchar-1'), (2,'varchar-2'), (3,'varchar-3'); +UPDATE t1 SET c1 = c1 + 10; +DELETE FROM t1 WHERE c1 = 12; + +--echo # +--echo # Do some statements on the non-transactional table. +--echo # +INSERT INTO t2 VALUES (1,'varchar-1'), (2,'varchar-2'), (3,'varchar-3'); +UPDATE t2 SET c1 = c1 + 10; +DELETE FROM t2 WHERE c1 = 12; + +--echo # +--echo # Rollback transaction. +--echo # +ROLLBACK; +SELECT * FROM t1; +SELECT * FROM t2; +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; + +--echo # +--echo # Flush all log buffers to the log file. +--echo # +FLUSH LOGS; + +--echo # +--echo # Call mysqlbinlog to display the log file contents. +--echo # +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /Xid = [0-9]*/Xid = #/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /server v [^ ]*/server v #.##.##/ /CRC32 0x[0-9a-f]*/CRC32 XXX/ /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ /xid=\d*/xid=<xid>/ +--exec $MYSQL_BINLOG --base64-output=decode-rows -v -v $MYSQLD_DATADIR/master-bin.000001 + +--echo # +--echo # Cleanup. +--echo # +DROP TABLE t1, t2; diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_start_alter_verbose.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_start_alter_verbose.test new file mode 100644 index 00000000..338326d1 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_start_alter_verbose.test @@ -0,0 +1,58 @@ +# +# Purpose: +# +# This test ensures that mysqlbinlog prints a comment when two-phase alter +# is enabled which shows the original alter query issued. +# +# +# References: +# MENT-662: Finalize MDEV-11675 "Lag Free Alter On Slave" +# + +# Just row format for faster testing +--source include/have_binlog_format_row.inc +--source include/have_innodb.inc + +#--- +# Setup +#--- +--let $binlog_alter_two_phase= `select @@binlog_alter_two_phase` +set global binlog_alter_two_phase = ON; +set binlog_alter_two_phase = ON; + +RESET MASTER; +create table myt (a int) engine=InnoDB; + + +#--- +# Issue ALTER +#--- +alter table myt add column (b int); + + +#--- +# Check binlog output +#--- +FLUSH LOGS; + +--disable_query_log +--let $MYSQLD_DATADIR= `select @@datadir` +--let $BINLOG_FILENAME= query_get_value(SHOW BINARY LOGS, Log_name, 1) + +--echo # Exec MYSQL_BINLOG --base64-output=decode-rows -v MYSQLD_DATADIR/BINLOG_FILENAME > MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql +--exec $MYSQL_BINLOG --base64-output=decode-rows -v $MYSQLD_DATADIR/$BINLOG_FILENAME > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql + +create table raw_binlog_rows (txt varchar(1000)); +--eval load data local infile '$MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql' into table raw_binlog_rows columns terminated by '\n' +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql +--enable_query_log +--echo Verbose statements from : $BINLOG_FILENAME +# Output --verbose lines, with extra Windows CR's trimmed +select replace(txt,'\r', '') as stmt from raw_binlog_rows where txt like '###%'; + +#--- +# Cleanup +#--- +drop table raw_binlog_rows; +drop table myt; +--eval set global binlog_alter_two_phase=$binlog_alter_two_phase diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_stop_never.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_stop_never.test new file mode 100644 index 00000000..b6a95c2c --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_stop_never.test @@ -0,0 +1,61 @@ +# ==== Purpose ==== +# +# Test verifies that continuous streaming of binary log content using the +# "mysqlbinlog --stop-never" option and sourcing it to mysql client works +# fine. +# +# ==== Implementation ==== +# +# Steps: +# 1 - Create a table on a server on which binary log is enabled and insert +# a row. +# 2 - Disable the binary log on the server and drop the table. +# 3 - Capture the binary log output using "mysqlbinlog --stop_never" option +# and source it to mysql client. +# 4 - Query the PROCESSLIST table to ensure that the dump thread which is +# serving "stop_never" option has read entire binlog. +# 5 - Verify that the table is populated on the server. +# 6 - Cleanup. +# +# ==== References ==== +# +# MDEV-11154: Write_on_release_cache(log_event.cc) function will not write +# "COMMIT", if use "mysqlbinlog ... | mysql ..." + +--source include/not_windows.inc + +# Test is not specific to any binlog format. Hence Running only for 'row'. +--source include/have_binlog_format_row.inc + +# binlog file name is needed in the test. To use master-bin.000001, +# RESET MASTER is needed. +RESET MASTER; +# kill the dump threads if there any dump threads (may be from previous test) +--source include/stop_dump_threads.inc + +--echo # Step-1: Execute some dummy statements. +CREATE TABLE t1(i int); +INSERT INTO t1 values (1); + +--echo # Step-2: Disable binary log temporarily and drop the table 't1'. +set @@SESSION.SQL_LOG_BIN = 0; +DROP TABLE t1; +set @@SESSION.SQL_LOG_BIN = 1; + +--echo # Step-3: Execute MYSQL_BINLOG with --stop-never and source it to mysql client. +--exec ($MYSQL_BINLOG --read-from-remote-server --stop-never --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 | $MYSQL --user=root --protocol=tcp --host=127.0.0.1 --port=$MASTER_MYPORT) < /dev/null > /dev/null 2>&1 & + +--echo # Step-4: Wait till dump thread transfer is completed. +let $wait_condition= SELECT id from information_schema.processlist where processlist.command like '%Binlog%' and state like '%Master has sent%'; +--source include/wait_condition.inc + +--echo # Step-5: Check that the data is there. +let $count= 1; +let $table= test.t1; +source include/wait_until_rows_count.inc; + +--echo # Step-6: Cleanup +--echo # kill the dump thread serving the mysqlbinlog --stop-never process +--source include/stop_dump_threads.inc + +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_suppress_O_TMPFILE.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_suppress_O_TMPFILE.test new file mode 100644 index 00000000..c97269a8 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_suppress_O_TMPFILE.test @@ -0,0 +1,51 @@ +# ==== Purpose ==== +# +# Suppress the following informational note that gets printed to standard +# error when O_TMPFILE flag is not supported by underlying operating system. +# +# Note: ../client/mysqlbinlog: O_TMPFILE is not supported on /tmp (disabling +# future attempts) +# +# Step 1: Generate a binarylog file with a size greater than 1MB. +# Step 2: Use mysqlbinlog tool to generate sql file and redirect the standard +# error to standard output (2>&1) +# Step 3: Source the generated sql file as inpurt to mysql client, observe no +# syntax error is reported. +# +# ==== References ==== +# +# MDEV-23846: O_TMPFILE error in mysqlbinlog stream output breaks restore +# +--source include/have_binlog_format_row.inc + +RESET MASTER; +CREATE TABLE t(f text); +INSERT INTO t VALUES (repeat('x',4096)); +INSERT INTO t SELECT * FROM t; +INSERT INTO t SELECT * FROM t; +INSERT INTO t SELECT * FROM t; +INSERT INTO t SELECT * FROM t; +INSERT INTO t SELECT * FROM t; +INSERT INTO t SELECT * FROM t; +INSERT INTO t SELECT * FROM t; +INSERT INTO t SELECT * FROM t; +INSERT INTO t SELECT * FROM t; +SELECT COUNT(*) FROM t; +FLUSH LOGS; +let $MYSQLD_DATADIR= `select @@datadir`; + +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql 2>&1 +# +# Clear database and restore from binlog +# +DROP TABLE t; + +--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql + +--echo # 512- Rows must be present +--let $assert_cond= COUNT(*) = 512 FROM t +--let $assert_text= Table t should have 512 rows. +--source include/assert.inc + +DROP TABLE t; +RESET MASTER; diff --git a/mysql-test/suite/binlog/t/binlog_no_uniqfile_crash.test b/mysql-test/suite/binlog/t/binlog_no_uniqfile_crash.test new file mode 100644 index 00000000..cb8b1078 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_no_uniqfile_crash.test @@ -0,0 +1,83 @@ +# ==== Purpose ==== +# +# Test verifies that when RESET MASTER TO # command is supplied with binlog +# extension number greater than 2147483647 the command should report +# appropriate error and binary log should be disabled. It should not result in +# a crash. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Verify case with max binary log extension. Max value is '2147483647' +# 1 - Confirm that SHOW BINARY LOGS displays a binary log with '2147483647' +# 2 - Verify that events are successfully written into max extension file. +# 3 - Try to create a binary log with extension greater than max allowed +# value '2147483648', verify ER_NO_UNIQUE_LOGFILE error is reported. +# 4 - Execute CREATE DATABASE db2 statement and verify server dosn't crash. +# 5 - Execute SHOW BINARY LOG command and verify that it reports +# ER_NO_BINARY_LOGGING error. +# 6 - Restart the server and verify that databse 'db2' exists and it it not +# present in the binary log. +# +# ==== References ==== +# +# MDEV-22451: SIGSEGV in __memmove_avx_unaligned_erms/memcpy from +# _my_b_write on CREATE after RESET MASTER +# +--source include/have_log_bin.inc + +call mtr.add_suppression("Next log extension: 2147483647. Remaining log filename extensions: 0"); +call mtr.add_suppression("Log filename extension number exhausted:."); +call mtr.add_suppression("Can't generate a unique log-filename"); +call mtr.add_suppression("MYSQL_BIN_LOG::open failed to generate new file name."); +call mtr.add_suppression("Could not use master-bin for logging"); + + +--echo "Test case verifies creation of binary log with max entension value." +RESET MASTER TO 2147483647; +--source include/show_binary_logs.inc + +# Check error log for correct messages. +let $log_error_= `SELECT @@GLOBAL.log_error`; +if(!$log_error_) +{ + # MySQL Server on windows is started with --console and thus + # does not know the location of its .err log, use default location + let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.1.err; +} + +--let SEARCH_FILE=$log_error_ +--let SEARCH_PATTERN=Next log extension: 2147483647. Remaining log filename extensions: 0. +--source include/search_pattern_in_file.inc + +CREATE DATABASE db1; +--source include/show_binlog_events.inc + +--error ER_NO_UNIQUE_LOGFILE +RESET MASTER TO 2147483648; + +--let SEARCH_FILE=$log_error_ +--let SEARCH_PATTERN=Turning logging off for the whole duration of the MariaDB server process +--source include/search_pattern_in_file.inc + +--echo "Following CREATE DATABSE db2 command will not be present in binary log" +--echo "as binary log got closed due to ER_NO_UNIQUE_LOGFILE error." +CREATE DATABASE db2; + + +--echo "RESET MASTER command fails to generate a new binary log" +--echo "log-bin will be disabled and server needs to be restarted to" +--echo "re-enable the binary log." +--error ER_NO_BINARY_LOGGING +SHOW BINARY LOGS; + +--source include/restart_mysqld.inc + +--source include/show_binary_logs.inc +SHOW DATABASES LIKE 'db%'; +--source include/show_binlog_events.inc + +# Cleanup +DROP DATABASE db1; +DROP DATABASE db2; +--source include/show_binlog_events.inc diff --git a/mysql-test/suite/binlog/t/binlog_old_versions.test b/mysql-test/suite/binlog/t/binlog_old_versions.test new file mode 100644 index 00000000..13010154 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_old_versions.test @@ -0,0 +1,153 @@ +# Test that old binlog formats can be read. + +# Some previous versions of MySQL use their own binlog format, +# especially in row-based replication. This test uses saved binlogs +# from those old versions to test that we can replicate from old +# versions to the present version. + +# Replicating from old versions to new versions is necessary in an +# online upgrade scenario, where the . + +# The previous versions we currently test are: +# - version 5.1.17 and earlier trees +# - mysql-5.1-wl2325-xxx trees (AKA alcatel trees) +# - mysql-5.1-telco-6.1 trees +# For completeness, we also test mysql-5.1-new_rpl, which is supposed +# to be the "correct" version. + +# All binlogs were generated with the same commands (listed at the end +# of this test for reference). The binlogs contain the following +# events: Table_map, Write_rows, Update_rows, Delete_rows Query, Xid, +# User_var, Int_var, Rand, Begin_load, Append_file, Execute_load. + +# Related bugs: BUG#27779, BUG#31581, BUG#31582, BUG#31583, BUG#32407 + +source include/not_embedded.inc; + +--echo ==== Read binlog with v2 row events ==== + +# Read binlog. +--exec $MYSQL_BINLOG --local-load=$MYSQLTEST_VARDIR/tmp/ suite/binlog/std_data/ver_trunk_row_v2.001 | $MYSQL --local-infile=1 +# Show result. +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT COUNT(*) FROM t3; +# Reset. +DROP TABLE t1, t2, t3; + + +--echo ==== Read modern binlog (version 5.1.23) ==== + +# Read binlog. +--exec $MYSQL_BINLOG --local-load=$MYSQLTEST_VARDIR/tmp/ suite/binlog/std_data/ver_5_1_23.001 | $MYSQL --local-infile=1 +# Show result. +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT COUNT(*) FROM t3; +# Reset. +DROP TABLE t1, t2, t3; + + +--echo ==== Read binlog from version 5.1.17 ==== + +# Read binlog. +--exec $MYSQL_BINLOG --local-load=$MYSQLTEST_VARDIR/tmp/ suite/binlog/std_data/ver_5_1_17.001 | $MYSQL --local-infile=1 +# Show result. +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT COUNT(*) FROM t3; +# Reset. +DROP TABLE t1, t2, t3; + + +--echo ==== Read binlog from version 4.1 ==== + +# In this version, neither row-based binlogging nor Xid events +# existed, so the binlog was generated without the "row-based tests" +# part and the "get xid event" part, and it does not create table t2. + +# Read binlog. +--exec $MYSQL_BINLOG --local-load=$MYSQLTEST_VARDIR/tmp/ suite/binlog/std_data/binlog_old_version_4_1.000001 | $MYSQL --local-infile=1 +# Show result. +SELECT * FROM t1 ORDER BY a; +SELECT COUNT(*) FROM t3; +# Reset. +DROP TABLE t1, t3; + + +--echo ==== Read binlog from telco tree (mysql-5.1-telco-6.1) ==== + +# Read binlog. +--exec $MYSQL_BINLOG --local-load=$MYSQLTEST_VARDIR/tmp/ suite/binlog/std_data/ver_5_1-telco.001 | $MYSQL --local-infile=1 +# Show resulting tablea. +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT COUNT(*) FROM t3; +# Reset. +DROP TABLE t1, t2, t3; + + +#### The following commands were used to generate the binlogs #### +# +#source include/master-slave.inc; +# +## ==== initialize ==== +#USE test; +#CREATE TABLE t1 (a int, b char(50)) ENGINE = MyISAM; +#CREATE TABLE t2 (a int, b char(50)) ENGINE = InnoDB; +#CREATE TABLE t3 (a char(20)); +# +# +## ==== row based tests ==== +#SET BINLOG_FORMAT='row'; +# +## ---- get write, update, and delete rows events ---- +#INSERT INTO t1 VALUES (0, 'one'), (1, 'two'); +#UPDATE t1 SET a=a+1; +#DELETE FROM t1 WHERE a=2; +# +# +## ==== statement based tests ==== +#SET BINLOG_FORMAT = 'statement'; +# +## ---- get xid events ---- +#BEGIN; +#INSERT INTO t2 VALUES (3, 'first stm in trx'); +#INSERT INTO t1 VALUES (3, 'last stm in trx: next event should be xid'); +#COMMIT; +# +## ---- get user var events ---- +#SET @x = 4; +#INSERT INTO t1 VALUES (@x, 'four'); +# +## ---- get rand event ---- +#INSERT INTO t1 VALUES (RAND() * 1000000, 'random'); +# +## ---- get intvar event ---- +#INSERT INTO t1 VALUES (LAST_INSERT_ID(), 'last_insert_id'); +# +## ---- get begin, append and execute load events ---- +## double the file until we have more than 2^17 bytes, so that the +## event has to be split and we can use Append_file_log_event. +# +#SET SQL_LOG_BIN=0; +#CREATE TABLE temp (a char(20)); +#LOAD DATA INFILE '../std_data_ln/words.dat' INTO TABLE temp; +#INSERT INTO temp SELECT * FROM temp; +#INSERT INTO temp SELECT * FROM temp; +#INSERT INTO temp SELECT * FROM temp; +#INSERT INTO temp SELECT * FROM temp; +#INSERT INTO temp SELECT * FROM temp; +#INSERT INTO temp SELECT * FROM temp; +#INSERT INTO temp SELECT * FROM temp; +#INSERT INTO temp SELECT * FROM temp; +#SELECT a FROM temp INTO OUTFILE 'big_file.dat'; +#DROP TABLE temp; +#SET SQL_LOG_BIN=1; +# +#LOAD DATA INFILE 'big_file.dat' INTO TABLE t3; +# +#SELECT * FROM t1 ORDER BY a; +#SELECT * FROM t2 ORDER BY a; +#SELECT COUNT(*) FROM t3; +#--source include/rpl_end.inc diff --git a/mysql-test/suite/binlog/t/binlog_parallel_replication_ddl.test b/mysql-test/suite/binlog/t/binlog_parallel_replication_ddl.test new file mode 100644 index 00000000..d861ecc9 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_parallel_replication_ddl.test @@ -0,0 +1,30 @@ +# Check binlog properties of various DDL:s. +# Motivated by MDEV-27365. +# +--source include/have_log_bin.inc +--source include/have_binlog_format_mixed.inc + +RESET MASTER; + +# MDEV-27365 CREATE-or-REPLACE SEQUENCE bilogged without DDL flag +# Prove it is logged with the DDL flag. +CREATE OR REPLACE SEQUENCE s1; + +# This one has been always correct. +DROP SEQUENCE s1; +FLUSH LOGS; + +--let $MYSQLD_DATADIR= `select @@datadir` +--exec $MYSQL_BINLOG --base64-output=decode-rows $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql + +--let SEARCH_PATTERN= GTID [0-9]+-[0-9]+-[0-9]+ +--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql +--source include/search_pattern_in_file.inc + +--echo The same as above number of samples must be found: +--let SEARCH_PATTERN= GTID [0-9]+-[0-9]+-[0-9]+ ddl +--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql +--source include/search_pattern_in_file.inc +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql + +--echo End of the tests diff --git a/mysql-test/suite/binlog/t/binlog_parallel_replication_marks_row.test b/mysql-test/suite/binlog/t/binlog_parallel_replication_marks_row.test new file mode 100644 index 00000000..82898486 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_parallel_replication_marks_row.test @@ -0,0 +1,3 @@ +--source include/have_log_bin.inc +--source include/have_binlog_format_row.inc +--source include/binlog_parallel_replication_marks.test diff --git a/mysql-test/suite/binlog/t/binlog_parallel_replication_marks_stm_mix.test b/mysql-test/suite/binlog/t/binlog_parallel_replication_marks_stm_mix.test new file mode 100644 index 00000000..15042b3a --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_parallel_replication_marks_stm_mix.test @@ -0,0 +1,3 @@ +--source include/have_log_bin.inc +--source include/have_binlog_format_mixed_or_statement.inc +--source include/binlog_parallel_replication_marks.test diff --git a/mysql-test/suite/binlog/t/binlog_query_filter_rules-master.opt b/mysql-test/suite/binlog/t/binlog_query_filter_rules-master.opt new file mode 100644 index 00000000..33632bf9 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_query_filter_rules-master.opt @@ -0,0 +1 @@ +--replicate-do-db='impossible_database' diff --git a/mysql-test/suite/binlog/t/binlog_query_filter_rules.test b/mysql-test/suite/binlog/t/binlog_query_filter_rules.test new file mode 100644 index 00000000..d56a32ce --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_query_filter_rules.test @@ -0,0 +1,32 @@ +# regression test for +# Bug#36099 replicate-do-db affects replaying RBR events with mysqlbinlog +# The test verifies that the slave side filtering rule does not affect +# applying of row-events on master via mysqlbinlog + +-- source include/have_log_bin.inc +-- source include/not_embedded.inc +-- source include/have_binlog_format_row.inc + +--disable_warnings +drop table if exists t1; +--enable_warnings + +reset master; + +create table t1 (a int); +insert into t1 values (1); + +let $MYSQLD_DATADIR= `select @@datadir`; +flush logs; +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/bug36099.sql + +drop table t1; +--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/bug36099.sql" + +--echo *** must be 1 *** +select * from t1; + +# cleanup + +drop table t1; +remove_file $MYSQLTEST_VARDIR/tmp/bug36099.sql; diff --git a/mysql-test/suite/binlog/t/binlog_recover_checksum_error.test b/mysql-test/suite/binlog/t/binlog_recover_checksum_error.test new file mode 100644 index 00000000..12c9f3d9 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_recover_checksum_error.test @@ -0,0 +1,37 @@ +# The test verifies server binlog-based recovery. +# +# MDEV-23832 checksum error at server binlog recovery should not crash + +# The test logic really requires --log-bin. +--source include/have_binlog_format_mixed.inc +--source include/have_debug.inc + +--let $do_checksum = `SELECT @@global.master_verify_checksum` +--let $debug_dbug_saved = `SELECT @@global.debug_dbug` +--let $binlog_checksum = `SELECT @@global.binlog_checksum` +set @@global.binlog_checksum = CRC32; + +call mtr.add_suppression("Replication event checksum verification failed"); +call mtr.add_suppression("Error in Log_event::read_log_event"); + +# Proof of no crash follows. +# There's no need for actual bin-loggable queries to the server +--let $restart_parameters= --master_verify_checksum=ON --debug_dbug="+d,corrupt_read_log_event_char" +--let $shutdown_timeout=0 +--source include/restart_mysqld.inc +--let $restart_parameters= +--let $shutdown_timeout= + +# +# Cleanup + +--replace_regex /= .*/= VALUE/ +--eval set @@global.debug_dbug = "$debug_dbug_saved" + +--replace_result $do_checksum DO_CHECKSUM +--eval set @@global.master_verify_checksum = $do_checksum +--replace_result $binlog_checksum BINLOG_CHECKSUM +--eval set @@global.binlog_checksum = $binlog_checksum +# +--echo # EOF the test +# diff --git a/mysql-test/suite/binlog/t/binlog_rotate_perf.test b/mysql-test/suite/binlog/t/binlog_rotate_perf.test new file mode 100644 index 00000000..74c91fec --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_rotate_perf.test @@ -0,0 +1,102 @@ +# ==== Purpose ==== +# +# functional test for open_binlog call using when +# +# flush log reset master/slave called +# +# ==== Related ==== +# +# TXSQL feature 67 binlog rotate perf optimization + +let $engine= myisam; + +--source include/have_binlog_format_row.inc +--connect(conn1,localhost,root,,test) + +reset master; +create database test_rotate_db; +use test_rotate_db; +--echo #currrent engine=$engine +# Create a new table +--replace_column 2 # +show binary logs; +--eval CREATE TABLE t1_$engine (c1 INT) ENGINE=$engine +--eval insert into t1_$engine values(0),(1) + +# do batch flush and show +let $loop_times= 100; +--source include/show_master_status.inc +while ($loop_times) { + flush logs; + flush logs; + if ($loop_times < 5) + { + --source include/show_master_status.inc + if ($loop_times == 4) + { + --source include/show_binary_logs.inc + } + reset master; + } + if ($loop_times >= 5) + { + flush logs; + } + + # + dec $loop_times; + --echo # left times= $loop_times +} +--echo # [engine=$engine] after first loop_times=$loop_times, show master logs results +--source include/show_binary_logs.inc + +# do batch flush and show with restart mysql +--source include/show_master_status.inc +let $loop_times= 10; +while ($loop_times) { + flush logs; + flush logs; + --echo #begin to restart mysqld current loop_times=$loop_times + --source include/restart_mysqld.inc + # + dec $loop_times; + --echo # left restart times= $loop_times +} +--echo # [engine=$engine] after second loop_times=$loop_times, show master logs results +--source include/show_binary_logs.inc + + +# try to change the log-bin configs and restart +--echo # ======= now try to change the log-bin config for mysqld ======= +--let $restart_parameters="--log-bin=new_log_bin" +--echo #begin to restart mysqld +--source include/restart_mysqld.inc +--let $restart_parameters= "" + +--source include/show_binary_logs.inc +let $loop_times= 10; +while ($loop_times) { + flush logs; + flush logs; + if ($loop_times < 5) + { + if ($loop_times == 4) + { + --source include/show_binary_logs.inc + } + reset master; + } + if ($loop_times >= 5) + { + flush logs; + } + + # + dec $loop_times; + --echo # left times= $loop_times +} +--echo # [engine=$engine] after third loop_times=$loop_times, show master logs results +--source include/show_binary_logs.inc + +##cleanup +drop database test_rotate_db; diff --git a/mysql-test/suite/binlog/t/binlog_row_annotate-master.opt b/mysql-test/suite/binlog/t/binlog_row_annotate-master.opt new file mode 100644 index 00000000..24d88646 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_row_annotate-master.opt @@ -0,0 +1 @@ +--timezone=GMT-3 --binlog-do-db=test1 --binlog-do-db=test2 --binlog-do-db=test3 diff --git a/mysql-test/suite/binlog/t/binlog_row_annotate.test b/mysql-test/suite/binlog/t/binlog_row_annotate.test new file mode 100644 index 00000000..a6e5f828 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_row_annotate.test @@ -0,0 +1 @@ +--source include/binlog_row_annotate.inc diff --git a/mysql-test/suite/binlog/t/binlog_row_binlog-master.opt b/mysql-test/suite/binlog/t/binlog_row_binlog-master.opt new file mode 100644 index 00000000..e4c44226 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_row_binlog-master.opt @@ -0,0 +1 @@ +--max_binlog_size=8192 --default-storage-engine=MyISAM diff --git a/mysql-test/suite/binlog/t/binlog_row_binlog.test b/mysql-test/suite/binlog/t/binlog_row_binlog.test new file mode 100644 index 00000000..7fa6a2ce --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_row_binlog.test @@ -0,0 +1,7 @@ +# This is a wrapper for binlog.test so that the same test case can be used +# For both statement and row based bin logs 9/19/2005 [jbm] + +-- source include/have_binlog_format_row.inc +let collation=utf8mb3_unicode_ci; +--source include/have_collation.inc +--source include/binlog.test diff --git a/mysql-test/suite/binlog/t/binlog_row_cache_stat.test b/mysql-test/suite/binlog/t/binlog_row_cache_stat.test new file mode 100644 index 00000000..6f406119 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_row_cache_stat.test @@ -0,0 +1,5 @@ +# This is a wrapper for binlog.test so that the same test case can be used +# For both statement and row based bin logs 9/19/2005 [jbm] + +-- source include/have_binlog_format_row.inc +-- source include/binlog_cache_stat.test diff --git a/mysql-test/suite/binlog/t/binlog_row_ctype_cp932.test b/mysql-test/suite/binlog/t/binlog_row_ctype_cp932.test new file mode 100644 index 00000000..b99afb6c --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_row_ctype_cp932.test @@ -0,0 +1,5 @@ +# This is a wrapper for binlog.test so that the same test case can be used +# For both statement and row based bin logs 9/19/2005 [jbm] + +-- source include/have_binlog_format_row.inc +-- source include/ctype_cp932.test diff --git a/mysql-test/suite/binlog/t/binlog_row_ctype_ucs.test b/mysql-test/suite/binlog/t/binlog_row_ctype_ucs.test new file mode 100644 index 00000000..02a9b647 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_row_ctype_ucs.test @@ -0,0 +1,6 @@ +# This is a wrapper for binlog.test so that the same test case can be used +# For both statement and row based bin logs 9/19/2005 [jbm] + +-- source include/have_binlog_format_row.inc +-- source include/ctype_ucs_binlog.test + diff --git a/mysql-test/suite/binlog/t/binlog_row_drop_tbl.test b/mysql-test/suite/binlog/t/binlog_row_drop_tbl.test new file mode 100644 index 00000000..82853065 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_row_drop_tbl.test @@ -0,0 +1,5 @@ +# This is a wrapper for drop_table.test so that the same test case can be used +# For both statement and row based bin logs + +-- source include/have_binlog_format_row.inc +-- source include/drop_table.test diff --git a/mysql-test/suite/binlog/t/binlog_row_drop_tmp_tbl.test b/mysql-test/suite/binlog/t/binlog_row_drop_tmp_tbl.test new file mode 100644 index 00000000..e45e659c --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_row_drop_tmp_tbl.test @@ -0,0 +1,5 @@ +# This is a wrapper for binlog.test so that the same test case can be used +# For both statement and row based bin logs 9/19/2005 [jbm] + +-- source include/have_binlog_format_row.inc +-- source include/drop_temp_table.test diff --git a/mysql-test/suite/binlog/t/binlog_row_innodb_stat-master.opt b/mysql-test/suite/binlog/t/binlog_row_innodb_stat-master.opt new file mode 100644 index 00000000..4cb92754 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_row_innodb_stat-master.opt @@ -0,0 +1 @@ +--binlog_cache_size=32768 diff --git a/mysql-test/suite/binlog/t/binlog_row_insert_select.test b/mysql-test/suite/binlog/t/binlog_row_insert_select.test new file mode 100644 index 00000000..e2a08536 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_row_insert_select.test @@ -0,0 +1,10 @@ +# This is a wrapper for binlog.test so that the same test case can be used +# For both statement and row based bin logs 9/19/2005 [jbm] + +-- source include/have_binlog_format_row.inc +# Bug#18326: Do not lock table for writing during prepare of statement +# The use of the ps protocol causes extra table maps in the binlog, so +# we disable the ps-protocol for this statement. +--disable_ps_protocol +-- source include/insert_select-binlog.test +--enable_ps_protocol diff --git a/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam-master.opt b/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam-master.opt new file mode 100644 index 00000000..a177f285 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam-master.opt @@ -0,0 +1 @@ +--loose-innodb-lock-wait-timeout=2 --default-storage-engine=MyISAM diff --git a/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam.test b/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam.test new file mode 100644 index 00000000..9692c6ee --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam.test @@ -0,0 +1,15 @@ +# This is a wrapper for binlog.test so that the same test case can be used +# For both statement and row based bin logs 9/19/2005 [jbm] + +-- source include/have_binlog_format_row.inc + +# Bug#18326: Do not lock table for writing during prepare of statement +# The use of the ps protocol causes extra table maps in the binlog, so +# we disable the ps-protocol for this statement. +--disable_ps_protocol + +-- source include/mix_innodb_myisam_binlog.test + +--enable_ps_protocol + +-- source include/mix_innodb_myisam_side_effects.test diff --git a/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_db_filter.test b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_db_filter.test new file mode 100644 index 00000000..2e3e53b8 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_db_filter.test @@ -0,0 +1,148 @@ +# BUG#42941: --database parameter to mysqlbinlog fails with RBR +# +# WHAT +# ==== +# +# This test aims at checking whether a rows log event is printed or +# not when --database parameter is used to filter events from one +# given database. +# +# HOW +# === +# +# The test is implemented as follows: +# +# i) Some operations are done in two different databases: +# 'test' and 'b42941'; +# ii) mysqlbinlog is used to dump the contents of the binlog file +# filtering only events from 'b42941'. The result of the dump is +# stored in a temporary file. (This is done with and without +# --verbose/hexdump flag); +# iii) The contents of the dump are loaded into a session variable; +# iv) The variable contents are searched for 'test' and 'b42941'; +# v) Should 'test' be found, an ERROR is reported. Should 'b42941' be +# absent, an ERROR is reported. + +-- source include/have_log_bin.inc +-- source include/have_binlog_format_row.inc +-- source include/have_innodb.inc + +RESET MASTER; +-- let $MYSQLD_DATADIR= `select @@datadir` + +CREATE TABLE t1 (id int); +CREATE TABLE t2 (id int); +CREATE TABLE t3 (txt TEXT); +CREATE TABLE t4 (a int) ENGINE= InnoDB; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t2 VALUES (1); +INSERT INTO t2 VALUES (2); +INSERT INTO t1 VALUES (3); +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/std_data/words.dat' INTO TABLE t3 +INSERT INTO t1 VALUES (4); + +CREATE DATABASE b42941; +use b42941; +CREATE TABLE t1 (id int); +CREATE TABLE t2 (id int); +CREATE TABLE t3 (txt TEXT); +CREATE TABLE t4 (a int) ENGINE= InnoDB; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t2 VALUES (1); +INSERT INTO t2 VALUES (2); +INSERT INTO t1 VALUES (3); +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/std_data/words.dat' INTO TABLE t3 +INSERT INTO t1 VALUES (4); + +INSERT INTO test.t1 VALUES (5); + +FLUSH LOGS; + +UPDATE test.t1 t11, b42941.t1 t12 SET t11.id=10, t12.id=100; + +BEGIN; +INSERT INTO test.t4 VALUES (1); +INSERT INTO b42941.t4 VALUES (1); +UPDATE test.t4 tn4, b42941.t4 tt4 SET tn4.a= 10, tt4.a= 100; +COMMIT; + +FLUSH LOGS; + +-- let $log_file1= $MYSQLD_DATADIR/master-bin.000001 +-- let $log_file2= $MYSQLD_DATADIR/master-bin.000002 +-- let $outfile= $MYSQLTEST_VARDIR/tmp/b42941-mysqlbinlog +-- let $cmd= $MYSQL_BINLOG + +let $i= 3; +while($i) +{ + -- let $flags=--database=b42941 + + # construct CLI for mysqlbinlog + if($i==3) + { + -- let $flags= $flags --verbose --hexdump + } + + if($i==2) + { + -- let $flags= $flags --verbose + } + +# if($i==1) +# { + # do nothing $flags is already set as it should be +# } + + # execute mysqlbinlog on the two available master binlog files + -- exec $cmd $flags $log_file1 > $outfile.1 + -- exec $cmd $flags $log_file2 > $outfile.2 + + # load outputs into a variable + -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR + -- eval SET @b42941_output.1= LOAD_FILE('$outfile.1') + + -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR + -- eval SET @b42941_output.2= LOAD_FILE('$outfile.2') + + # remove unecessary files + -- remove_file $outfile.1 + -- remove_file $outfile.2 + + # + # The two tests are canceled since we introduced the patch of bug#46998, + # which will make mydsqlbinlog output the 'BEGIN', 'COMMIT' and 'ROLLBACK' + # in regardless of database filtering + # + # assertion: events for database test are filtered + #if (`SELECT INSTR(@b42941_output.1, 'test')`) + #{ + #-- echo **** ERROR **** Database name 'test' FOUND in mysqlbinlog output ($flags $outfile.1). + #} + + #if (`SELECT INSTR(@b42941_output.2, 'test')`) + #{ + #-- echo **** ERROR **** Database name 'test' FOUND in mysqlbinlog output ($flags $outfile.2). + #} + + # assertion: events for database b42941 are not filtered + if (!`SELECT INSTR(@b42941_output.1, 'b42941')`) + { + -- echo **** ERROR **** Database name 'b42941' NOT FOUND in mysqlbinlog output ($flags $outfile.1). + } + + if (!`SELECT INSTR(@b42941_output.2, 'b42941')`) + { + -- echo **** ERROR **** Database name 'b42941' NOT FOUND in mysqlbinlog output ($flags $outfile.2). + } + + dec $i; +} + +DROP DATABASE b42941; +use test; +DROP TABLE t1, t2, t3, t4; diff --git a/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options-master.opt b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options-master.opt new file mode 100644 index 00000000..4d69f335 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options-master.opt @@ -0,0 +1 @@ +--timezone=GMT-3 diff --git a/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options.test b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options.test new file mode 100644 index 00000000..159b0186 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options.test @@ -0,0 +1,78 @@ +--source include/have_log_bin.inc +--source include/have_binlog_format_row.inc + +# +# MWL36: Add a mysqlbinlog option to change the used database +# (Adding --rewrite-db option) +# +--disable_warnings +DROP DATABASE IF EXISTS test1; +DROP DATABASE IF EXISTS test2; +DROP DATABASE IF EXISTS test3; +--enable_warnings + +# For SBR --rewrite-db affects only default database and doesn't affect +# a query (specifically CREATE DATABASE) itself. Hence (for testing +# purpose) we start binary logging after all databases have been created. + +CREATE DATABASE test1; +CREATE DATABASE test2; +CREATE DATABASE test3; + +# Fix timestamp to avoid varying results. +SET timestamp=1000000000; + +# Delete all existing binary logs. +RESET MASTER; + +# We'll call mysqlbinlog with two rewrite rules: +# --rewrite-db="test1->new_test1" +# --rewrite-db="test3->new_test3" + +USE test1; +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,1),(2,2); + +USE test2; +CREATE TABLE t2 (a INT); +INSERT INTO t2 VALUES (1),(2); + +DELETE FROM test1.t1 WHERE a=1; + +USE test3; +CREATE TABLE t3 (a INT); +INSERT INTO t3 VALUES (1),(2); +INSERT INTO test1.t1 VALUES (3,3); + +USE test1; +LOAD DATA INFILE '../../std_data/loaddata7.dat' INTO TABLE t1 + FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n'; +DELETE FROM test3.t3 WHERE a=1; + +flush logs; + +--echo # +--echo # mysqlbinlog output +--echo # --base64-output = decode-rows +--echo # --rewrite-db = test1->new_test1 +--echo # --rewrite-db = test3->new_test3 +--echo # + +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_regex /server id [0-9]*/server id #/ /server v [^ ]*/server v #.##.##/ /exec_time=[0-9]*/exec_time=#/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /CRC32 0x[0-9a-f]*/CRC32 XXX/ /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ /xid=\d*/xid=<xid>/ +--exec $MYSQL_BINLOG --base64-output=decode-rows --rewrite-db="test1->new_test1" --rewrite-db="test3->new_test3" -v -v $MYSQLD_DATADIR/master-bin.000001 + +--echo # +--echo # mysqlbinlog output +--echo # --base64-output = decode-rows +--echo # --rewrite-db = test1->new_test1 +--echo # --rewrite-db = test3->new_test3 +--echo # --read-from-remote-server +--echo # + +--replace_regex /server id [0-9]*/server id #/ /server v [^ ]*/server v #.##.##/ /exec_time=[0-9]*/exec_time=#/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /CRC32 0x[0-9a-f]*/CRC32 XXX/ /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ /xid=\d*/xid=<xid>/ +--exec $MYSQL_BINLOG --base64-output=decode-rows --rewrite-db="test1->new_test1" --rewrite-db="test3->new_test3" -v -v --read-from-remote-server --user=root --host=localhost --port=$MASTER_MYPORT master-bin.000001 + +DROP DATABASE test1; +DROP DATABASE test2; +DROP DATABASE test3; diff --git a/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_verbose.test b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_verbose.test new file mode 100644 index 00000000..98aa7635 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_verbose.test @@ -0,0 +1,69 @@ +######################################################## +# WHAT +# ==== +# This test aims to check that the mysqlbinlog --verbose +# command can output binlogs in 4 format variants. +# +# 1) Updates logged as write_row events +# Only primary key and updated columns included in the +# event +# 2) Updates logged as write_row_events +# All columns included in the event +# 3) Updates logged as update_row events +# Only primary key and updated columns included in the +# event +# 4) Updates logged as update_row events +# All columns included in the event +######################################################## + +# We require binlog_format_row as we're independent of binlog format +# and there's no point running the same test 3 times +-- source include/have_binlog_format_row.inc + +--disable_query_log +--let $binlog_file=write-partial-row.binlog +--exec $MYSQL_BINLOG --verbose suite/binlog/std_data/$binlog_file > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql +create table raw_binlog_rows (txt varchar(1000)); +--eval load data local infile '$MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql' into table raw_binlog_rows columns terminated by '\n'; +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql +--enable_query_log +--echo Verbose statements from : $binlog_file +# Output --verbose lines, with extra Windows CR's trimmed +select replace(txt,'\r', '') as stmt from raw_binlog_rows where txt like '###%'; +drop table raw_binlog_rows; + +--disable_query_log +--let $binlog_file=write-full-row.binlog +--exec $MYSQL_BINLOG --verbose suite/binlog/std_data/$binlog_file > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql +create table raw_binlog_rows (txt varchar(1000)); +--eval load data local infile '$MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql' into table raw_binlog_rows columns terminated by '\n'; +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql +--enable_query_log +--echo Verbose statements from : $binlog_file +# Output --verbose lines, with extra Windows CR's trimmed +select replace(txt,'\r', '') as stmt from raw_binlog_rows where txt like '###%'; +drop table raw_binlog_rows; + +--disable_query_log +--let $binlog_file=update-partial-row.binlog +--exec $MYSQL_BINLOG --verbose suite/binlog/std_data/$binlog_file > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql +create table raw_binlog_rows (txt varchar(1000)); +--eval load data local infile '$MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql' into table raw_binlog_rows columns terminated by '\n'; +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql +--enable_query_log +--echo Verbose statements from : $binlog_file +# Output --verbose lines, with extra Windows CR's trimmed +select replace(txt,'\r', '') as stmt from raw_binlog_rows where txt like '###%'; +drop table raw_binlog_rows; + +--disable_query_log +--let $binlog_file=update-full-row.binlog +--exec $MYSQL_BINLOG --verbose suite/binlog/std_data/$binlog_file > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql +create table raw_binlog_rows (txt varchar(1000)); +--eval load data local infile '$MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql' into table raw_binlog_rows columns terminated by '\n'; +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql +--enable_query_log +--echo Verbose statements from : $binlog_file +# Output --verbose lines, with extra Windows CR's trimmed +select replace(txt,'\r', '') as stmt from raw_binlog_rows where txt like '###%'; +drop table raw_binlog_rows; diff --git a/mysql-test/suite/binlog/t/binlog_server_id.test b/mysql-test/suite/binlog/t/binlog_server_id.test new file mode 100644 index 00000000..6e98ec6e --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_server_id.test @@ -0,0 +1,29 @@ +# Test for BUG#28908 Replication: set global server_id is not setting the session server_id + +-- source include/have_log_bin.inc + +let $saved_server_id=`select @@server_id`; +set global server_id=1; +reset master; + +-- disable_warnings +drop table if exists t1,t2,t3; +-- enable_warnings + +create table t1 (a int); +select @@server_id; +source include/show_binlog_events2.inc; + +set global server_id=2; +create table t2 (b int); +select @@server_id; +source include/show_binlog_events2.inc; + +set global server_id=3; +create table t3 (c int); +select @@server_id; +source include/show_binlog_events2.inc; + +# cleanup +eval set global server_id=$saved_server_id; +drop table t1,t2,t3; diff --git a/mysql-test/suite/binlog/t/binlog_sf.test b/mysql-test/suite/binlog/t/binlog_sf.test new file mode 100644 index 00000000..fecc4736 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_sf.test @@ -0,0 +1,187 @@ + +# We change binlog format inside the test, so no need to re-run with +# more than one binlog_format. +-- source include/have_binlog_format_statement.inc + +# Bug#16456 RBR: rpl_sp.test expects query to fail, but passes in RBR +# BUG#41166 stored function requires "deterministic" if binlog_format is "statement" + +# save status + +let $otfc=`select @@log_bin_trust_function_creators`; +set global log_bin_trust_function_creators=0; + +# fail *on definition* + +set binlog_format=STATEMENT; + +delimiter |; +--error ER_BINLOG_UNSAFE_ROUTINE +create function fn16456() + returns int +begin + return unix_timestamp(); +end| +delimiter ;| + + + +# force in definition, so we can see whether we fail on call + +set global log_bin_trust_function_creators=1; + +delimiter |; +create function fn16456() + returns int +begin + return unix_timestamp(); +end| +delimiter ;| + +set global log_bin_trust_function_creators=0; + + + +# allow funcall in RBR + +set binlog_format=ROW; + +--replace_column 1 timestamp +select fn16456(); + + + +# fail funcall in SBR + +set binlog_format=STATEMENT; + +--error ER_BINLOG_UNSAFE_ROUTINE +select fn16456(); + + + +# clean + +drop function fn16456; + + + +# success in definition with deterministic + +set global log_bin_trust_function_creators=0; + +delimiter |; +create function fn16456() + returns int deterministic +begin + return unix_timestamp(); +end| +delimiter ;| + + + +# allow funcall in RBR + +set binlog_format=ROW; + +--replace_column 1 timestamp +select fn16456(); + + + +# allow funcall in SBR + +set binlog_format=STATEMENT; + +--replace_column 1 timestamp +select fn16456(); + + + +# clean + +drop function fn16456; + + +# success in definition with NO SQL + +set global log_bin_trust_function_creators=0; + +delimiter |; +create function fn16456() + returns int no sql +begin + return unix_timestamp(); +end| +delimiter ;| + + + +# allow funcall in RBR + +set binlog_format=ROW; + +--replace_column 1 timestamp +select fn16456(); + + + +# allow funcall in SBR + +set binlog_format=STATEMENT; + +--replace_column 1 timestamp +select fn16456(); + + +# clean + +drop function fn16456; + + + +# success in definition with reads sql data + +set global log_bin_trust_function_creators=0; + +delimiter |; +create function fn16456() + returns int reads sql data +begin + return unix_timestamp(); +end| +delimiter ;| + + + +# allow funcall in RBR + +set binlog_format=ROW; + +--replace_column 1 timestamp +select fn16456(); + + + +# allow funcall in SBR + +set binlog_format=STATEMENT; + +--replace_column 1 timestamp +select fn16456(); + + + +# clean + +drop function fn16456; + + + +# restore status + +--disable_query_log +set binlog_format=STATEMENT; +eval set global log_bin_trust_function_creators=$otfc; +reset master; +--enable_query_log diff --git a/mysql-test/suite/binlog/t/binlog_show_binlog_event_random_pos.combinations b/mysql-test/suite/binlog/t/binlog_show_binlog_event_random_pos.combinations new file mode 100644 index 00000000..72076e12 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_show_binlog_event_random_pos.combinations @@ -0,0 +1,5 @@ +[enable_checksum] +binlog_checksum=1 + +[disable_checksum] +binlog_checksum=0 diff --git a/mysql-test/suite/binlog/t/binlog_show_binlog_event_random_pos.test b/mysql-test/suite/binlog/t/binlog_show_binlog_event_random_pos.test new file mode 100644 index 00000000..05e6967c --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_show_binlog_event_random_pos.test @@ -0,0 +1,42 @@ +# ==== Purpose ==== +# +# Test verifies that reading binary log by using "SHOW BINLOG EVENTS" command +# from various random positions doesn't lead to crash. It should exit +# gracefully with appropriate error. +# +# ==== References ==== +# +# MDEV-18046:Assortment of crashes, assertion failures and ASAN errors in mysql_show_binlog_events + +--source include/have_log_bin.inc +--source include/have_innodb.inc + +RESET MASTER; +call mtr.add_suppression("Error in Log_event::read_log_event*"); +call mtr.add_suppression("Replication event checksum verification failed while reading from a log file*"); + +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (c1 CHAR(255), c2 CHAR(255), c3 CHAR(255), c4 CHAR(255), c5 CHAR(255)); +INSERT INTO t1 VALUES (repeat('a', 255), repeat('a', 255),repeat('a', 255),repeat('a', 255),repeat('a', 255)); +INSERT INTO t1 VALUES (repeat('a', 255), repeat('a', 255),repeat('a', 255),repeat('a', 255),repeat('a', 255)); +UPDATE t1 SET c1=repeat('b',255); +INSERT INTO t1 VALUES (repeat('a', 255), repeat('a', 255),repeat('a', 255),repeat('a', 255),repeat('a', 255)); +--let $max_pos= query_get_value(SHOW MASTER STATUS,Position,1) +--let $pos= 1 +while ($pos <= $max_pos) +{ + --disable_query_log + --disable_result_log + --error 0,1220 + eval SHOW BINLOG EVENTS FROM $pos LIMIT 100; + --inc $pos + --enable_result_log + --enable_query_log +} + +# Testing a case where input position is greater than actual binlog file size. +--replace_result $pos POS $max_pos MAX_POS +--error 1220 +eval SHOW BINLOG EVENTS FROM $pos; + +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/binlog_spurious_ddl_errors.test b/mysql-test/suite/binlog/t/binlog_spurious_ddl_errors.test new file mode 100644 index 00000000..29a86076 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_spurious_ddl_errors.test @@ -0,0 +1,95 @@ +################################################################################ +# BUG#50479 DDL stmt on row-only/stmt-only tables generate spurious +# binlog_format errors +# +# In the fix of BUG#39934 in 5.1-rep+3, errors are generated when +# binlog_format=row and a statement modifies a table restricted to +# statement-logging (ER_BINLOG_ROW_MODE_AND_STMT_ENGINE); or if +# binlog_format=statement and a statement modifies a table limited to +# row-logging (ER_BINLOG_STMT_MODE_AND_ROW_ENGINE). +# +# In this test case, we check if some DDL statements that lock tables do not +# trigger errors as they do not generate rows events and as such are harmless +# from the point of view of conflicts between the engine's supported logging +# format and the value of binlog_format. +# +# In particular, we check if: +# 1 - ALTER TABLE, CREATE INDEX and CREATE TRIGGER do not generate either +# ER_BINLOG_STMT_MODE_AND_ROW_ENGINE or ER_BINLOG_STMT_MODE_AND_ROW_ENGINE +# +# 2 - CREATE TABLE ... SELECT generates an error because the command can +# generate row events but CREATE TABLE without SELECT does not generate +# an error. +################################################################################ +--source include/have_innodb.inc +--source include/have_example_plugin.inc +--source include/have_log_bin.inc + +SET @old_binlog_format= @@global.binlog_format; +INSTALL PLUGIN example SONAME 'ha_example'; + +--echo ################################################################################ +--echo # Verifies if ER_BINLOG_STMT_MODE_AND_ROW_ENGINE happens by setting the binlog +--echo # format to STATEMENT and the transaction isolation level to READ COMMITTED as +--echo # such changes force Innodb to accept changes in the row format. +--echo # +--echo # When CREATE TABLE, ALTER TABLE, CREATE INDEX and CREATE TRIGGER are executed +--echo # any error should be triggered. +--echo # +--echo # In contrast, CREATE TABLE ... SELECT should trigger the following error: +--echo # ER_BINLOG_STMT_MODE_AND_ROW_ENGINE. +--echo ################################################################################ +SET binlog_format = STATEMENT; +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +CREATE TABLE t_row (a VARCHAR(100)) ENGINE = InnoDB; + +ALTER TABLE t_row ADD COLUMN b INT; + +CREATE TRIGGER trig_row BEFORE INSERT ON t_row FOR EACH ROW INSERT INTO t_stmt VALUES (1); + +CREATE INDEX i ON t_row(a); + +--error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE +CREATE TABLE t_row_new ENGINE = InnoDB SELECT * FROM t_row; + +DROP TABLE t_row; + +--echo +--echo + +--echo ################################################################################ +--echo # Verifies if ER_BINLOG_ROW_MODE_AND_STMT_ENGINE happens by setting the binlog +--echo # format to ROW and using a engine, i.e. EXAMPLE, that only supports STATEMENT. +--echo # +--echo # When CREATE TABLE, ALTER TABLE, CREATE INDEX and CREATE TRIGGER are executed +--echo # the error ER_BINLOG_ROW_MODE_AND_STMT_ENGINE is not triggered. Note that other +--echo # errors are triggered due to restrictions in the engine. +--echo # +--echo # In contrast, CREATE TABLE ... SELECT should trigger the following error: +--echo # ER_BINLOG_ROW_MODE_AND_STMT_ENGINE. +--echo ################################################################################ +SET binlog_format = ROW; +CREATE TABLE t_stmt (a VARCHAR(100)) ENGINE = EXAMPLE; + +ALTER TABLE t_stmt ADD COLUMN b INT; + +CREATE TRIGGER trig_stmt BEFORE INSERT ON t_stmt FOR EACH ROW INSERT INTO t_stmt VALUES (1); + +--error ER_TOO_MANY_KEY_PARTS +CREATE INDEX i ON t_stmt(a); + +--error ER_BINLOG_ROW_MODE_AND_STMT_ENGINE +CREATE TABLE t_stmt_new ENGINE = EXAMPLE SELECT * FROM t_stmt; + +DROP TABLE t_stmt; + +--echo +--echo + +--echo ################################################################################ +--echo # CLEAN UP # +--echo ################################################################################ +flush tables; +UNINSTALL PLUGIN example; +SET @@global.binlog_format = @old_binlog_format; +SET @@session.binlog_format = @old_binlog_format; diff --git a/mysql-test/suite/binlog/t/binlog_sql_mode.test b/mysql-test/suite/binlog/t/binlog_sql_mode.test new file mode 100644 index 00000000..167c8f5a --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_sql_mode.test @@ -0,0 +1,171 @@ +# ==== Purpose ==== +# +# Test that sql_mode can correct restore before generating the binlog event +# when creating CREATEable objects. +# +# ==== Method ==== +# +# Scan binlog file to check if the sql_mode is still set to 0 before generating binlog event +# + +-- source include/have_log_bin.inc + +# BUG#39526 sql_mode not retained in binary log for CREATE PROCEDURE + +SET @old_sql_mode= @@global.sql_mode; +SET @old_binlog_format=@@session.binlog_format; +let $MYSQLD_DATADIR= `select @@datadir`; +SET SESSION sql_mode=8; + +--echo Initialization + +RESET MASTER; +CREATE TABLE t1 (id INT); + +CREATE PROCEDURE testProc() SELECT * FROM t1; +CREATE VIEW testView as SELECT * from t1; + +DELIMITER |; +CREATE FUNCTION testFunc() + RETURNS INT + BEGIN + return 1; + END;| +DELIMITER ;| + +DELIMITER |; +CREATE TRIGGER testTrig BEFORE INSERT ON t1 + FOR EACH ROW BEGIN + UPDATE t1 SET id = id +1; + END;| +DELIMITER ;| + +DELIMITER |; +CREATE EVENT testEvent ON SCHEDULE + EVERY 1 DAY + DO + BEGIN + UPDATE t1 SET id = id +1; + END;| +DELIMITER ;| + +--echo Check Result + +let $MYSQLD_DATADIR= `select @@datadir`; +--exec $MYSQL_BINLOG --force-if-open $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug39526.binlog +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval select +(@a:=load_file("$MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug39526.binlog")) +is not null; +let $s_mode_unsigned= `select @a like "%@@session.sql_mode=0%" /* must return 0 */`; +echo *** String sql_mode=0 is found: $s_mode_unsigned ***; + +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug39526.binlog + +--echo Clean Up + +DROP PROCEDURE testProc; +DROP FUNCTION testFunc; +DROP TRIGGER testTrig; +DROP EVENT testEvent; +DROP VIEW testView; +DROP TABLE t1; + +SET @@global.sql_mode= @old_sql_mode; +SET @@session.binlog_format=@old_binlog_format; + +--echo +--echo # +--echo # Test for Bug#12601974 - STORED PROCEDURE SQL_MODE=NO_BACKSLASH_ESCAPES +--echo # IGNORED AND BREAKS REPLICATION +--echo # + +--disable_warnings +DROP DATABASE IF EXISTS mysqltest_db; +DROP TABLE IF EXISTS test_table; +--enable_warnings + +CREATE DATABASE mysqltest_db; +USE mysqltest_db; +CREATE TABLE test_table (c1 CHAR(50)); + +SET @org_mode=@@sql_mode; + +SET @@sql_mode=''; +DELIMITER $; +CREATE PROCEDURE proc_without_sql_mode (IN param1 CHAR(50), IN param2 CHAR(50)) +BEGIN + DECLARE var1 CHAR(50) DEFAULT param1; + DECLARE var2 CHAR(50) DEFAULT param2; + DECLARE var3 CHAR(50) DEFAULT 'abcd\bef'; + DECLARE var4 CHAR(50) DEFAULT 'abcd\nef'; + DECLARE var5 CHAR(50) DEFAULT 'abcd\ref'; + DECLARE var6 CHAR(50) DEFAULT 'abcd\tef'; + DECLARE var7 CHAR(50) DEFAULT 'abcd\\ef'; + DECLARE var8 CHAR(50) DEFAULT 'abcd\%ef'; + DECLARE var9 CHAR(50) DEFAULT 'abcd\_ef'; + + INSERT INTO test_table VALUES (var1); + INSERT INTO test_table VALUES (var2); + INSERT INTO test_table VALUES (var3); + INSERT INTO test_table VALUES (var4); + INSERT INTO test_table VALUES (var5); + INSERT INTO test_table VALUES (var6); + INSERT INTO test_table VALUES (var7); + INSERT INTO test_table VALUES (var8); + INSERT INTO test_table VALUES (var9); +END +$ + +SET @@sql_mode='NO_BACKSLASH_ESCAPES'$ +CREATE PROCEDURE proc_with_sql_mode (IN param1 CHAR(50), IN param2 CHAR(50)) +BEGIN + DECLARE var1 CHAR(50) DEFAULT param1; + DECLARE var2 CHAR(50) DEFAULT param2; + DECLARE var3 CHAR(50) DEFAULT 'wxyz\bef'; + DECLARE var4 CHAR(50) DEFAULT 'wxyz\nef'; + DECLARE var5 CHAR(50) DEFAULT 'wxyz\ref'; + DECLARE var6 CHAR(50) DEFAULT 'wxyz\tef'; + DECLARE var7 CHAR(50) DEFAULT 'wxyz\\ef'; + DECLARE var8 CHAR(50) DEFAULT 'wxyz\%ef'; + DECLARE var9 CHAR(50) DEFAULT 'wxyz\_ef'; + + INSERT INTO test_table VALUES (var1); + INSERT INTO test_table VALUES (var2); + INSERT INTO test_table VALUES (var3); + INSERT INTO test_table VALUES (var4); + INSERT INTO test_table VALUES (var5); + INSERT INTO test_table VALUES (var6); + INSERT INTO test_table VALUES (var7); + INSERT INTO test_table VALUES (var8); + INSERT INTO test_table VALUES (var9); +END +$ + +DELIMITER ;$ +SET @@sql_mode=''; +CALL proc_without_sql_mode('abcd\'ef', 'abcd\"ef'); +CALL proc_with_sql_mode('wxyz\'ef', 'wxyz\"ef'); +SELECT * FROM test_table; + +let $MYSQLD_DATADIR= `select @@datadir`; +--exec $MYSQL_BINLOG --force-if-open -d mysqltest_db $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug12601974.binlog + +--echo "Dropping table test_table" +DROP TABLE test_table; + +--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug12601974.binlog" + +--echo #"test_table" content after replaying the binlog +SELECT * FROM test_table; + +--echo #Clean up +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug12601974.binlog +DROP DATABASE mysqltest_db; +SET @@sql_mode= @org_mode; +use test; + +--echo +--echo #End of Test for Bug#12601974 + + diff --git a/mysql-test/suite/binlog/t/binlog_start_comment.test b/mysql-test/suite/binlog/t/binlog_start_comment.test new file mode 100644 index 00000000..98f2ca05 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_start_comment.test @@ -0,0 +1,25 @@ +# Test case for bug#32205 Replaying statements from mysqlbinlog fails +# with a syntax error, replicates fine + +source include/have_log_bin.inc; +source include/have_local_infile.inc; + +reset master; +--disable_warnings +drop table if exists t1,t2; +--enable_warnings +create table t1 (word varchar(20)) -- create table t1; +create table t2 (word varchar(20)) -- create table t2; +load data infile '../../std_data/words.dat' into table t1 -- load data to t1; +insert into t2 values ("Ada"); +flush logs; +select * from t2; +let $MYSQLD_DATADIR= `select @@datadir`; +--exec $MYSQL_BINLOG --local-load=$MYSQLTEST_VARDIR/tmp/ $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_start_comment.binlog +--exec $MYSQL --local-infile=1 < $MYSQLTEST_VARDIR/tmp/binlog_start_comment.binlog +flush logs; +select * from t2; + +# clean up +drop table t1,t2; +remove_file $MYSQLTEST_VARDIR/tmp/binlog_start_comment.binlog; diff --git a/mysql-test/suite/binlog/t/binlog_statement_insert_delayed.test b/mysql-test/suite/binlog/t/binlog_statement_insert_delayed.test new file mode 100644 index 00000000..9145afc0 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_statement_insert_delayed.test @@ -0,0 +1,13 @@ +# This test is to verify replication with INSERT DELAY through +# unrecommended STATEMENT binlog format + +-- source include/not_embedded.inc +-- source include/have_binlog_format_statement.inc +-- disable_query_log +reset master; # get rid of previous tests binlog +-- enable_query_log +disable_query_log; +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +enable_query_log; +-- source include/binlog_insert_delayed.test +reset master; diff --git a/mysql-test/suite/binlog/t/binlog_stm_binlog-master.opt b/mysql-test/suite/binlog/t/binlog_stm_binlog-master.opt new file mode 100644 index 00000000..099f07e5 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_binlog-master.opt @@ -0,0 +1 @@ +--max_binlog_size=4096 --default-storage-engine=MyISAM diff --git a/mysql-test/suite/binlog/t/binlog_stm_binlog.test b/mysql-test/suite/binlog/t/binlog_stm_binlog.test new file mode 100644 index 00000000..045be97d --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_binlog.test @@ -0,0 +1,20 @@ +-- source include/not_embedded.inc +-- source include/have_binlog_format_mixed.inc +let collation=utf8mb3_unicode_ci; +--source include/have_collation.inc + +reset master; # clear up binlogs +# REQUIREMENT +# replace_regex should replace output of SHOW BINLOG EVENTS + +create table t1 (a int, b int) engine=innodb; +begin; +insert into t1 values (1,2); +commit; +source include/show_binlog_events.inc; +drop table t1; + +# This is a wrapper for binlog.test so that the same test case can be used +# For both statement and row based bin logs 9/19/2005 [jbm] + +-- source include/binlog.test diff --git a/mysql-test/suite/binlog/t/binlog_stm_blackhole.test b/mysql-test/suite/binlog/t/binlog_stm_blackhole.test new file mode 100644 index 00000000..9dea4d1b --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_blackhole.test @@ -0,0 +1,6 @@ +# This is a wrapper for binlog.test so that the same test case can be used +# For both statement and row based bin logs 9/19/2005 [jbm] + +-- source include/not_embedded.inc +-- source include/have_binlog_format_statement.inc +-- source include/blackhole.test diff --git a/mysql-test/suite/binlog/t/binlog_stm_cache_stat.test b/mysql-test/suite/binlog/t/binlog_stm_cache_stat.test new file mode 100644 index 00000000..a03f4c54 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_cache_stat.test @@ -0,0 +1,5 @@ +# This is a wrapper for binlog.test so that the same test case can be used +# For both statement and row based bin logs 9/19/2005 [jbm] + +-- source include/have_binlog_format_statement.inc +-- source include/binlog_cache_stat.test diff --git a/mysql-test/suite/binlog/t/binlog_stm_ctype_cp932.test b/mysql-test/suite/binlog/t/binlog_stm_ctype_cp932.test new file mode 100644 index 00000000..33378b28 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_ctype_cp932.test @@ -0,0 +1,6 @@ +# This is a wrapper for binlog.test so that the same test case can be used +# For both statement and row based bin logs 9/19/2005 [jbm] + +-- source include/not_embedded.inc +-- source include/have_binlog_format_mixed_or_statement.inc +-- source include/ctype_cp932.test diff --git a/mysql-test/suite/binlog/t/binlog_stm_ctype_ucs.test b/mysql-test/suite/binlog/t/binlog_stm_ctype_ucs.test new file mode 100644 index 00000000..ed5b899c --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_ctype_ucs.test @@ -0,0 +1,6 @@ +# This is a wrapper for binlog.test so that the same test case can be used +# For both statement and row based bin logs 9/19/2005 [jbm] + +-- source include/have_binlog_format_mixed_or_statement.inc +-- source include/ctype_ucs_binlog.test + diff --git a/mysql-test/suite/binlog/t/binlog_stm_datetime_ranges_mdev15289.test b/mysql-test/suite/binlog/t/binlog_stm_datetime_ranges_mdev15289.test new file mode 100644 index 00000000..d277db97 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_datetime_ranges_mdev15289.test @@ -0,0 +1,7 @@ +--source include/not_embedded.inc +--source include/have_binlog_format_statement.inc +reset master; # clear up binlogs +--exec $MYSQL_CLIENT_TEST test_datetime_ranges_mdev15289 > $MYSQLTEST_VARDIR/log/binlog_stm_datetime_ranges_mysql_client_test.out.log 2>&1 + +--let $binlog_file = LAST +source include/show_binlog_events.inc; diff --git a/mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt b/mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt new file mode 100644 index 00000000..e2cfcb29 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt @@ -0,0 +1 @@ +--binlog-do-db=b42829 diff --git a/mysql-test/suite/binlog/t/binlog_stm_do_db.test b/mysql-test/suite/binlog/t/binlog_stm_do_db.test new file mode 100644 index 00000000..3ed1734f --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_do_db.test @@ -0,0 +1,90 @@ +# BUG#42829: binlogging enabled for all schemas regardless of +# binlog-db-db / binlog-ignore-db +# +# WHAT +# ==== +# +# We want to test whether filtered events from binlog will cause +# raising an error mentioning that statement is unable to be logged or +# not, when: +# +# 1. isolation level READ-COMMITTED; AND +# +# 2. using InnoDB engine; AND +# +# 3. using SBL (in which case InnoDB will only allow RBL). +# +# HOW +# === +# +# The test is implemented as follows: +# +# i) set tx_isolation to read-committed. +# +# ii) create two databases (one filtered other not - using +# binlog-do-db) +# +# iii) Create statements that are to be filtered on filtered db +# +# - At this point, before fix, an error would be raised +# +# iv) do the same thing for not the filtered database and check +# that events throw an error: +# +# - Error: ER_BINLOG_STMT_MODE_AND_ROW_ENGINE +# + +-- source include/have_log_bin.inc +-- source include/have_innodb.inc +-- source include/have_binlog_format_statement.inc +RESET MASTER; # clear up binlogs +SET @old_isolation_level= @@session.tx_isolation; +SET @@session.tx_isolation= 'READ-COMMITTED'; + +-- let $engine= InnoDB +-- let $filtered= b42829_filtered +-- let $not_filtered= b42829 + +-- eval CREATE DATABASE $not_filtered +-- eval use $not_filtered +-- eval CREATE TABLE t1 (x int, y int) engine=$engine +-- eval CREATE TABLE t2 (x int, y int) engine=$engine + +-- eval CREATE DATABASE $filtered +-- eval use $filtered +-- eval CREATE TABLE t1 (x int, y int) engine=$engine +-- eval CREATE TABLE t2 (x int, y int) engine=$engine + +SET @@session.sql_log_bin= 0; +-- eval INSERT INTO $filtered.t1 VALUES (100,100) +-- eval INSERT INTO $not_filtered.t1 VALUES (100,100) +SET @@session.sql_log_bin= 1; + +-- echo ### assertion: the inserts will not raise log error because +-- echo ### binlog-do-db is filtering used database +INSERT INTO t2 VALUES (1,2), (1,3), (1,4); +INSERT INTO t1 SELECT * FROM t2; + +-- echo ### assertion: assert that despite updating a not filtered +-- echo ### database this wont trigger an error as the +-- echo ### used database is the filtered one. +-- eval UPDATE $filtered.t1 ft1, $not_filtered.t1 nft1 SET ft1.x=1, nft1.x=2 + +-- eval use $not_filtered +-- echo ### assertion: the statements *will* raise log error because +-- echo ### binlog-do-db is not filtering used database +BEGIN; +-- error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE +INSERT INTO t2 VALUES (1,2), (1,3), (1,4); +-- error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE +-- eval UPDATE $filtered.t1 ft1, $not_filtered.t1 nft1 SET ft1.x=1, nft1.x=2 +-- error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE +INSERT INTO t1 SELECT * FROM t2; +COMMIT; + +-- echo ### assertion: filtered events did not make into the binlog +source include/show_binlog_events.inc; + +-- eval DROP DATABASE $not_filtered +-- eval DROP DATABASE $filtered +SET @@session.tx_isolation= @old_isolation_level; diff --git a/mysql-test/suite/binlog/t/binlog_stm_drop_tbl.test b/mysql-test/suite/binlog/t/binlog_stm_drop_tbl.test new file mode 100644 index 00000000..fb8b290a --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_drop_tbl.test @@ -0,0 +1,5 @@ +# This is a wrapper for drop_table.test so that the same test case can be used +# For both statement and row based bin logs + +-- source include/have_binlog_format_mixed_or_statement.inc +-- source include/drop_table.test diff --git a/mysql-test/suite/binlog/t/binlog_stm_drop_tmp_tbl.test b/mysql-test/suite/binlog/t/binlog_stm_drop_tmp_tbl.test new file mode 100644 index 00000000..201aa45b --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_drop_tmp_tbl.test @@ -0,0 +1,5 @@ +# This is a wrapper for binlog.test so that the same test case can be used +# For both statement and row based bin logs 9/19/2005 [jbm] + +-- source include/have_binlog_format_mixed_or_statement.inc +-- source include/drop_temp_table.test diff --git a/mysql-test/suite/binlog/t/binlog_stm_innodb_stat-master.opt b/mysql-test/suite/binlog/t/binlog_stm_innodb_stat-master.opt new file mode 100644 index 00000000..4cb92754 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_innodb_stat-master.opt @@ -0,0 +1 @@ +--binlog_cache_size=32768 diff --git a/mysql-test/suite/binlog/t/binlog_stm_insert_select.test b/mysql-test/suite/binlog/t/binlog_stm_insert_select.test new file mode 100644 index 00000000..d0782c70 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_insert_select.test @@ -0,0 +1,5 @@ +# This is a wrapper for binlog.test so that the same test case can be used +# For both statement and row based bin logs 9/19/2005 [jbm] + +-- source include/have_binlog_format_mixed_or_statement.inc +-- source include/insert_select-binlog.test diff --git a/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam-master.opt b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam-master.opt new file mode 100644 index 00000000..0fa355b4 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam-master.opt @@ -0,0 +1 @@ +--loose-innodb-lock-wait-timeout=2 --binlog-direct-non-transactional-updates=FALSE --default-storage-engine=MyISAM diff --git a/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test new file mode 100644 index 00000000..911c90b5 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test @@ -0,0 +1,15 @@ +# This is a wrapper for binlog.test so that the same test case can be used +# For both statement and row based bin logs 9/19/2005 [jbm] + +-- source include/have_binlog_format_statement.inc + +CALL mtr.add_suppression("Statement may not be safe to log in statement format."); + +-- source include/mix_innodb_myisam_binlog.test + +set @@session.binlog_format=statement; +-- source include/mix_innodb_myisam_side_effects.test +set @@session.binlog_format=@@global.binlog_format; + + +--echo end of tests diff --git a/mysql-test/suite/binlog/t/binlog_stm_ps.test b/mysql-test/suite/binlog/t/binlog_stm_ps.test new file mode 100644 index 00000000..b83991b1 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_ps.test @@ -0,0 +1,117 @@ +# This test is to verify replication with PS + +-- source include/not_embedded.inc +-- source include/have_binlog_format_statement.inc + +disable_query_log; +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +enable_query_log; + +-- disable_query_log +reset master; # get rid of previous tests binlog +-- enable_query_log + +--disable_warnings +drop table if exists t1; +--enable_warnings +reset master; + +# +# Bug #26842: master binary log contains invalid queries - replication fails +# +create table t1 (a int); +prepare s from "insert into t1 values (@a),(?)"; +set @a=98; execute s using @a; +prepare s from "insert into t1 values (?)"; +set @a=99; execute s using @a; +prepare s from "insert into t1 select 100 limit ?"; +set @a=100; execute s using @a; +source include/show_binlog_events.inc; +drop table t1; + +--echo # +--echo # MDEV-10709 Expressions as parameters to Dynamic SQL +--echo # + +FLUSH LOGS; +SET TIMESTAMP=UNIX_TIMESTAMP('2001-01-02 10:20:30.123456'); +CREATE TABLE t1 (a DECIMAL(30,8)); +PREPARE stmt FROM 'INSERT INTO t1 VALUES (?)'; +EXECUTE stmt USING 10; +EXECUTE stmt USING 11e0; +EXECUTE stmt USING 12.1; +EXECUTE stmt USING '13'; +EXECUTE stmt USING CURRENT_DATE; +EXECUTE stmt USING MAKETIME(10,20,30); +EXECUTE stmt USING CURRENT_TIME; +EXECUTE stmt USING CURRENT_TIME(3); +EXECUTE stmt USING CURRENT_TIME(6); +EXECUTE stmt USING CURRENT_TIMESTAMP; +EXECUTE stmt USING CURRENT_TIMESTAMP(3); +EXECUTE stmt USING CURRENT_TIMESTAMP(6); +SELECT * FROM t1; +--let $binlog_file = LAST +source include/show_binlog_events.inc; +DROP TABLE t1; +SET TIMESTAMP=DEFAULT; + +--echo # +--echo # MDEV-10585 EXECUTE IMMEDIATE statement +--echo # + +FLUSH LOGS; +CREATE TABLE t1 (a INT); +EXECUTE IMMEDIATE 'INSERT INTO t1 VALUES (101)'; +SET @a=102; +EXECUTE IMMEDIATE 'INSERT INTO t1 VALUES (?)' USING @a; +SET @a=103; +SET @stmt='INSERT INTO t1 VALUES (?)'; +EXECUTE IMMEDIATE @stmt USING @a; +--let $binlog_file = LAST +source include/show_binlog_events.inc; +DROP TABLE t1; + +--echo # +--echo # MDEV-11360 Dynamic SQL: DEFAULT as a bind parameter +--echo # + +FLUSH LOGS; +CREATE TABLE t1 (a INT DEFAULT 10); +EXECUTE IMMEDIATE 'INSERT INTO t1 VALUES (Default)'; +--echo # The output of this query in 'Note' is a syntactically incorrect query. +--echo # But as it's never logged, it's ok. It should be human readable only. +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT ?' USING Default; +EXECUTE IMMEDIATE 'INSERT INTO t1 VALUES (?)' USING Default; + +DELIMITER $$; +CREATE PROCEDURE p1 () +BEGIN + INSERT INTO t1 VALUES (Default); + # EXPLAIN should not be logged + EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT ?' USING Default; + EXECUTE IMMEDIATE 'INSERT INTO t1 VALUES (?)' USING Default; +END; +$$ +DELIMITER ;$$ +CALL p1; +DROP PROCEDURE p1; +DROP TABLE t1; + +--let $binlog_file = LAST +source include/show_binlog_events.inc; + +--echo # +--echo #MDEV-14467 Item_param: replace {INT|DECIMAL|REAL|STRING|TIME}_VALUE with Type_handler +--echo # + +FLUSH LOGS; +CREATE TABLE t1 (a INT); +EXECUTE IMMEDIATE 'INSERT INTO t1 SELECT 1 LIMIT ?' USING 10; +EXECUTE IMMEDIATE 'INSERT INTO t1 SELECT 1 LIMIT ?' USING 10.1; +EXECUTE IMMEDIATE 'INSERT INTO t1 SELECT 1 LIMIT ?' USING 10.1e0; +EXECUTE IMMEDIATE 'INSERT INTO t1 SELECT 1 LIMIT ?' USING '10'; +EXECUTE IMMEDIATE 'INSERT INTO t1 SELECT 1 LIMIT ?' USING TIME'10:10:10'; +DROP TABLE t1; + +--let $binlog_file = LAST +source include/show_binlog_events.inc; diff --git a/mysql-test/suite/binlog/t/binlog_stm_row.test b/mysql-test/suite/binlog/t/binlog_stm_row.test new file mode 100644 index 00000000..bef6b6e6 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_row.test @@ -0,0 +1,103 @@ +--source include/have_log_bin.inc +# Test sets its own binlog_format, so we restrict it to run only once +--source include/have_binlog_format_row.inc + +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); + +# Get rid of previous tests binlog +--disable_query_log +reset master; +--enable_query_log + +# +# Bug#34306: Can't make copy of log tables when server binary log is enabled +# +# This is an additional test for Bug#34306 in order to ensure that INSERT INTO +# .. SELECT FROM is properly replicated under SBR and RBR and that the proper +# read lock type are acquired. +# + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +--enable_warnings + +set @saved_global_binlog_format = @@global.binlog_format; +set @saved_local_binlog_format = @@session.binlog_format; +SET GLOBAL BINLOG_FORMAT = STATEMENT; +SET SESSION BINLOG_FORMAT = STATEMENT; + +CREATE TABLE t1 (a INT); +CREATE TABLE t2 LIKE t1; +select @@SESSION.BINLOG_FORMAT; +INSERT INTO t1 VALUES(1); +INSERT INTO t2 VALUES(2); + +--connect(con1,localhost,root,,) +--connect(con2,localhost,root,,) + +--echo # +--echo # Ensure that INSERT INTO .. SELECT FROM under SBR takes a read +--echo # lock that will prevent the source table from being modified. +--echo # + +--disable_ps2_protocol +--connection con1 +SELECT GET_LOCK('Bug#34306', 120); +--connection con2 +PREPARE stmt FROM "INSERT INTO t1 SELECT * FROM t2 WHERE GET_LOCK('Bug#34306', 120)"; +--send EXECUTE stmt; +--connection default +let $wait_condition= + SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE + state = "User lock" AND + info = "INSERT INTO t1 SELECT * FROM t2 WHERE GET_LOCK('Bug#34306', 120)"; +--source include/wait_condition.inc +--send INSERT INTO t2 VALUES (3); +--connection con1 +let $wait_condition= + SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE + state = "Waiting for table level lock" and info = "INSERT INTO t2 VALUES (3)"; +--source include/wait_condition.inc +SELECT RELEASE_LOCK('Bug#34306'); +--connection con2 +--reap +SELECT RELEASE_LOCK('Bug#34306'); +--connection default +--reap + +--echo # +--echo # Ensure that INSERT INTO .. SELECT FROM prepared under SBR does +--echo # not prevent the source table from being modified if under RBR. +--echo # + +--connection con2 +SET SESSION BINLOG_FORMAT = ROW; +--connection con1 +SELECT GET_LOCK('Bug#34306', 120); +--connection con2 +--send EXECUTE stmt; +--connection default +let $wait_condition= + SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE + state = "User lock" AND + info = "INSERT INTO t1 SELECT * FROM t2 WHERE GET_LOCK('Bug#34306', 120)"; +--source include/wait_condition.inc +--connection con1 +INSERT INTO t2 VALUES (4); +SELECT RELEASE_LOCK('Bug#34306'); +--connection con2 +--reap +--enable_ps2_protocol + +--disconnect con1 +--disconnect con2 +--connection default + +--echo # Show binlog events +source include/show_binlog_events.inc; + +DROP TABLE t1; +DROP TABLE t2; +SET GLOBAL BINLOG_FORMAT = @saved_global_binlog_format; +SET SESSION BINLOG_FORMAT = @saved_local_binlog_format; diff --git a/mysql-test/suite/binlog/t/binlog_stm_sp.test b/mysql-test/suite/binlog/t/binlog_stm_sp.test new file mode 100644 index 00000000..047cab74 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_sp.test @@ -0,0 +1,82 @@ +--source include/have_binlog_format_statement.inc + +--disable_query_log +reset master; # get rid of previous tests binlog +--enable_query_log + +--echo # +--echo # MDEV-11815 SP variables of temporal data types do not replicate correctly +--echo # + +CREATE TABLE t1(a INT); +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN + DECLARE i INT DEFAULT 123; + DECLARE b8 BIT(8) DEFAULT 0x61; + DECLARE t0 TIME DEFAULT '01:01:01'; + DECLARE t6 TIME(6) DEFAULT '01:01:01.123456'; + DECLARE d DATE DEFAULT '2001-01-01'; + DECLARE dt0 DATETIME DEFAULT '2001-01-01 01:01:01'; + DECLARE dt6 DATETIME(6) DEFAULT '2001-01-01 01:01:01.123456'; + DECLARE ts0 TIMESTAMP DEFAULT '2001-01-01 01:01:01'; + DECLARE ts6 TIMESTAMP(6) DEFAULT '2001-01-01 01:01:01.123456'; + INSERT INTO t1 VALUES (i=0x61); + INSERT INTO t1 VALUES (b8=0x61); + INSERT INTO t1 VALUES (t0=10101); + INSERT INTO t1 VALUES (t6=10101); + INSERT INTO t1 VALUES (d=20010101); + INSERT INTO t1 VALUES (dt0=20010101010101); + INSERT INTO t1 VALUES (dt6=20010101010101); + INSERT INTO t1 VALUES (ts0=20010101010101); + INSERT INTO t1 VALUES (ts6=20010101010101); +END; +$$ +DELIMITER ;$$ +CALL p1; +DROP TABLE t1; +DROP PROCEDURE p1; + +--let $binlog_file = LAST +source include/show_binlog_events.inc; + +--echo # +--echo # MDEV-16020 SP variables inside GROUP BY..WITH ROLLUP break replication +--echo # + +FLUSH LOGS; +CREATE TABLE t1 (d DATE); +INSERT INTO t1 VALUES ('1985-05-13'),('1989-12-24'); +CREATE TABLE t2 (d DATE, c BIGINT); +DELIMITER $$; +BEGIN NOT ATOMIC + BEGIN + DECLARE var INT DEFAULT 10; + INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, var; + INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, var WITH ROLLUP; + END; + BEGIN + DECLARE atomic INT DEFAULT 20; + INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, atomic; + INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, atomic WITH ROLLUP; + INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, `atomic`; + INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, `atomic` WITH ROLLUP; + END; + BEGIN + DECLARE atomic ROW (atomic INT, xxx INT) DEFAULT (31,32); + INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, atomic.atomic; + INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, atomic.atomic WITH ROLLUP; + INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, `atomic`.`atomic`; + INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, `atomic`.`atomic` WITH ROLLUP; + INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, atomic.xxx; + INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, atomic.xxx WITH ROLLUP; + INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, `atomic`.`xxx`; + INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, `atomic`.`xxx` WITH ROLLUP; + END; +END; +$$ +DELIMITER ;$$ +DROP TABLE t1,t2; + +--let $binlog_file = LAST +source include/show_binlog_events.inc; diff --git a/mysql-test/suite/binlog/t/binlog_stm_sp_type_row.test b/mysql-test/suite/binlog/t/binlog_stm_sp_type_row.test new file mode 100644 index 00000000..a7e21ee5 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_sp_type_row.test @@ -0,0 +1,108 @@ +--source include/not_embedded.inc +--source include/have_binlog_format_statement.inc + +--disable_query_log +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +reset master; # get rid of previous tests binlog +--enable_query_log + + +SET sql_mode=ORACLE; + +--echo # +--echo # MDEV-10914 ROW data type for stored routine variables +--echo # + +CREATE TABLE t1 (a INT, b INT); +DELIMITER $$; +CREATE PROCEDURE p1 +AS + rec ROW(a INT,b INT); +BEGIN + rec.a:=100; + rec.b:=200; + INSERT INTO t1 VALUES (rec.a,rec.b); + INSERT INTO t1 VALUES (10, rec=ROW(100,200)); + INSERT INTO t1 VALUES (10, ROW(100,200)=rec); + INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE rec=ROW(100,200); + INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=rec; + rec.a:=NULL; + INSERT INTO t1 VALUES (11, rec=ROW(100,200)); + INSERT INTO t1 VALUES (11, rec=ROW(100,201)); + INSERT INTO t1 VALUES (11, ROW(100,200)=rec); + INSERT INTO t1 VALUES (11, ROW(100,201)=rec); + INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE rec=ROW(100,200); + INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=rec; + rec.b:=NULL; + INSERT INTO t1 VALUES (12, rec=ROW(100,200)); + INSERT INTO t1 VALUES (12, ROW(100,200)=rec); + INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE rec=ROW(100,200); + INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=rec; +END; +$$ +DELIMITER ;$$ +CALL p1(); +SELECT * FROM t1; +DROP TABLE t1; +DROP PROCEDURE p1; +--let $binlog_file = LAST +source include/show_binlog_events.inc; + + +--echo # +--echo # Testing ROW fields in LIMIT +--echo # + +FLUSH LOGS; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (10),(10); +CREATE TABLE t2 (a INT); +DELIMITER $$; +CREATE PROCEDURE p1() +AS + a INT:= 1; + rec ROW(a INT); +BEGIN + rec.a:= 1; + INSERT INTO t2 SELECT 1 FROM t1 LIMIT a; + INSERT INTO t2 SELECT 2 FROM t1 LIMIT rec.a; +END; +$$ +DELIMITER ;$$ +CALL p1(); +DROP TABLE t1,t2; +DROP PROCEDURE p1; +--let $binlog_file = LAST +source include/show_binlog_events.inc; + + +--echo # +--echo # End of MDEV-10914 ROW data type for stored routine variables +--echo # + + +--echo # +--echo # MDEV-12291 Allow ROW variables as SELECT INTO targets +--echo # + +FLUSH LOGS; +SET sql_mode=DEFAULT; +CREATE TABLE t1 (a INT, b VARCHAR(32)); +INSERT INTO t1 VALUES (10, 'b10'); +CREATE TABLE t2 LIKE t1; +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN + DECLARE rec1 ROW(a INT, b VARCHAR(32)); + SELECT * INTO rec1 FROM t1; + INSERT INTO t2 VALUES (rec1.a, rec1.b); +END; +$$ +DELIMITER ;$$ +CALL p1(); +SELECT * FROM t1; +DROP TABLE t1; +DROP TABLE t2; +DROP PROCEDURE p1; +--let $binlog_file = LAST +source include/show_binlog_events.inc; diff --git a/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning-master.opt b/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning-master.opt new file mode 100644 index 00000000..2dda40e6 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning-master.opt @@ -0,0 +1 @@ +--binlog-ignore-db=b42851 --log-error --log-bin=master-bin --log-bin-index=master-bin diff --git a/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test b/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test new file mode 100644 index 00000000..578f0ff5 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test @@ -0,0 +1,208 @@ +# BUG#42851: Spurious "Statement is not safe to log in statement +# format." warnings +# +# WHY +# === +# +# This test aims at checking that the fix that removes spurious +# entries in the error log when the statement is filtered out from +# binlog, is working. +# +# HOW +# === +# +# The test case is split into three assertions when issuing statements +# containing LIMIT and ORDER BY: +# +# i) issue statements in database that is not filtered => check +# that warnings ARE shown; +# +# ii) issue statements in database that is not filtered, but with +# binlog disabled => check that warnings ARE NOT shown; +# +# iii) issue statements in database that is filtered => check that +# warnings ARE NOT shown. + +-- source include/have_log_bin.inc +-- source include/have_binlog_format_statement.inc +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT."); + +-- echo ### NOT filtered database => assertion: warnings ARE shown + +-- disable_warnings +DROP TABLE IF EXISTS t1; +-- enable_warnings + +CREATE TABLE t1 (a int, b int, primary key (a)); +INSERT INTO t1 VALUES (1,2), (2,3); +UPDATE t1 SET b='4' WHERE a=1 LIMIT 1; +UPDATE t1 SET b='5' WHERE a=2 ORDER BY a LIMIT 1; +DROP TABLE t1; + +-- echo ### NOT filtered database => assertion: binlog disabled and warnings ARE NOT shown + +SET SQL_LOG_BIN= 0; + +-- disable_warnings +DROP TABLE IF EXISTS t1; +-- enable_warnings + +CREATE TABLE t1 (a int, b int, primary key (a)); +INSERT INTO t1 VALUES (1,2), (2,3); +UPDATE t1 SET b='4' WHERE a=1 LIMIT 1; +UPDATE t1 SET b='5' WHERE a=2 ORDER BY a LIMIT 1; +DROP TABLE t1; + +SET SQL_LOG_BIN= 1; + +-- echo ### FILTERED database => assertion: warnings ARE NOT shown + +let $old_db= `SELECT DATABASE()`; + +CREATE DATABASE b42851; +USE b42851; + +-- disable_warnings +DROP TABLE IF EXISTS t1; +-- enable_warnings + +CREATE TABLE t1 (a int, b int, primary key (a)); +INSERT INTO t1 VALUES (1,2), (2,3); +UPDATE t1 SET b='4' WHERE a=1 LIMIT 1; +UPDATE t1 SET b='5' WHERE a=2 ORDER BY a LIMIT 1; +DROP TABLE t1; + +CREATE TABLE t1 (a VARCHAR(1000)); +INSERT INTO t1 VALUES (CURRENT_USER()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (FOUND_ROWS()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (GET_LOCK('tmp', 1)); #marked unsafe in BUG#47995 +INSERT INTO t1 VALUES (IS_FREE_LOCK('tmp')); #marked unsafe in BUG#47995 +INSERT INTO t1 VALUES (IS_USED_LOCK('tmp')); #marked unsafe in BUG#47995 +INSERT INTO t1 VALUES (LOAD_FILE('../../std_data/words2.dat')); #marked unsafe in BUG#39701 +INSERT INTO t1 VALUES (MASTER_POS_WAIT('dummy arg', 4711, 1)); +INSERT INTO t1 VALUES (RELEASE_LOCK('tmp')); #marked unsafe in BUG#47995 +INSERT INTO t1 VALUES (ROW_COUNT()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (SESSION_USER()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (SLEEP(1)); #marked unsafe in BUG#47995 +INSERT INTO t1 VALUES (SYSDATE()); #marked unsafe in BUG#47995 +INSERT INTO t1 VALUES (SYSTEM_USER()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (USER()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (UUID()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (UUID_SHORT()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (VERSION()); #marked unsafe in BUG#47995 +INSERT INTO t1 VALUES (RAND()); #marked unsafe in BUG#49222 + +# clean up +DROP DATABASE b42851; + +eval USE $old_db; + +--echo # +--echo # Bug#46265: Can not disable warning about unsafe statements for binary logging +--echo # + +let BINLOG_COUNTER1= `select CONVERT(NOW(),UNSIGNED) as timestmap from dual`; + +SET @old_log_warnings = @@log_warnings; + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings +CREATE TABLE t1 (a VARCHAR(36), b VARCHAR(15)); + +SET GLOBAL LOG_WARNINGS = 0; +# Replacing the result file content here. +# Instead of writing $BINLOG_COUNTER1 value to result file, +# writing a fixed string timestamp to it. +--replace_result $BINLOG_COUNTER1 timestamp +eval INSERT INTO t1 VALUES(UUID(), '$BINLOG_COUNTER1'); +SET GLOBAL LOG_WARNINGS = 1; +--replace_result $BINLOG_COUNTER1 timestamp +eval INSERT INTO t1 VALUES(UUID(), '$BINLOG_COUNTER1'); +DROP TABLE t1; + +SET GLOBAL log_warnings = @old_log_warnings; + +let $log_error_= `SELECT @@GLOBAL.log_error`; +if(!$log_error_) +{ + # MySQL Server on windows is started with --console and thus + # does not know the location of its .err log, use default location + let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.1.err; +} + +# Assign env variable LOG_ERROR +let LOG_ERROR=$log_error_; + +--echo # Count the number of times the "Unsafe" message was printed +--echo # to the error log. + +perl; + use strict; + use Cwd; + my $log_error= $ENV{'LOG_ERROR'} or die "LOG_ERROR not set"; + open(FILE, "$log_error") or die("Unable to open '$log_error' from directory " . cwd() . " :$! \n"); + my $binlog_counter= $ENV{'BINLOG_COUNTER1'} or die "BINLOG_COUNTER1 not set"; + my $count = () = grep(/$binlog_counter/g,<FILE>); + # Grep the timestamp value from the error file. + print "Occurrences: $count\n"; + close(FILE); +EOF + +# +# Check how RAND() can be used with replication +# + +create table t1 (n1 int, n2 int, n3 int, + key (n1, n2, n3), + key (n2, n3, n1), + key (n3, n1, n2)); +insert into t1 values (1,1,1); +# This should work fine +insert into t1 values (RAND()*1000+10, RAND()*1000+10, RAND()*1000+10); +# This should need row based logging. +update t1 set n1=rand() where n1=1; +delete from t1 where n2=1 + rand()*0; +drop table t1; + +# bug#50192: diplaying the unsafe warning comes out to the user warning stack +-- disable_warnings +DROP TABLE IF EXISTS t1, t2; +-- enable_warnings + +CREATE TABLE t1 (a int); +CREATE TABLE t2 (a int auto_increment primary key, b int); +CREATE TRIGGER tr_bug50192 AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t2 (b) VALUES (1); + +DELIMITER |; + +CREATE FUNCTION sf_bug50192() RETURNS INTEGER +BEGIN + INSERT INTO t2(b) VALUES(2); + RETURN 1; +END | + +DELIMITER ;| + +INSERT INTO t1 VALUES (0); +SHOW WARNINGS; +SELECT sf_bug50192(); +SHOW WARNINGS; + +# The test proves MDEV-24617 fixes leave in force +# unsafe warnings in non-deterministic CREATE..SELECT cases. +# Below an inserted default value to `b` of the target table is replication +# unsafe. A warning must be out. +CREATE TABLE t3 (a INT(11) DEFAULT NULL); +INSERT INTO t3 VALUES (1); +CREATE TABLE t4 (a INT(11) DEFAULT NULL, b BIGINT(20) DEFAULT uuid_short()) SELECT * FROM t3; +SHOW WARNINGS; +# no warning out of a deterministic "rhs" of SELECT +CREATE OR REPLACE TABLE t4 (a INT(11) DEFAULT NULL) SELECT * FROM t3; +SHOW WARNINGS; + +# cleanup + +DROP FUNCTION sf_bug50192; +DROP TRIGGER tr_bug50192; +DROP TABLE t1, t2, t3, t4; diff --git a/mysql-test/suite/binlog/t/binlog_stm_user_variables.test b/mysql-test/suite/binlog/t/binlog_stm_user_variables.test new file mode 100644 index 00000000..85bf511a --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_user_variables.test @@ -0,0 +1,87 @@ +-- source include/have_binlog_format_statement.inc +RESET MASTER; +# +# BUG#49562: SBR out of sync when using numeric data types + user variable +# + +-- let $max_unsigned_long= 18446744073709551615 +-- let $min_signed_long= -9223372036854775808 +-- eval SET @positive= $max_unsigned_long +-- eval SET @negative= $min_signed_long + +CREATE TABLE t1 (`tinyint` TINYINT, + `smallint` SMALLINT, + `mediumint` MEDIUMINT, + `integer` INTEGER, + `bigint` BIGINT, + `utinyint` TINYINT UNSIGNED, + `usmallint` SMALLINT UNSIGNED, + `umediumint` MEDIUMINT UNSIGNED, + `uinteger` INTEGER UNSIGNED, + `ubigint` BIGINT UNSIGNED, + `double` DOUBLE, + `float` FLOAT, + `real` REAL(30,2), + `decimal` DECIMAL(30,2)) ENGINE = MyISAM; + +-- echo ### insert max unsigned +-- echo ### a) declarative +-- disable_warnings +-- eval INSERT IGNORE INTO t1 VALUES ($max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long,$max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long); +-- enable_warnings +TRUNCATE t1; + +-- echo ### b) user var +-- disable_warnings +INSERT IGNORE INTO t1 VALUES (@positive, + @positive, + @positive, + @positive, + @positive, + @positive, + @positive, + @positive, + @positive, + @positive, + @positive, + @positive, + @positive, + @positive); +-- enable_warnings + +-- echo ## assertion: checks that User_var_log_event::pack_info +-- echo ## correctly displays the binlog content by taking into +-- echo ## account the unsigned_flag +-- source include/show_binlog_events.inc + +-- echo ### insert min signed +-- echo ### a) declarative +-- disable_warnings +-- eval INSERT IGNORE INTO t1 VALUES ($min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long,$min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long); +-- enable_warnings +TRUNCATE t1; + +-- echo ### b) user var +-- disable_warnings +INSERT IGNORE INTO t1 VALUES (@negative, + @negative, + @negative, + @negative, + @negative, + @negative, + @negative, + @negative, + @negative, + @negative, + @negative, + @negative, + @negative, + @negative); +-- enable_warnings + +-- echo ## assertion: checks that User_var_log_event::pack_info +-- echo ## correctly displays the binlog content by taking into +-- echo ## account the unsigned_flag +-- source include/show_binlog_events.inc + +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/binlog_switch_inside_trans.test b/mysql-test/suite/binlog/t/binlog_switch_inside_trans.test new file mode 100644 index 00000000..a93cd44f --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_switch_inside_trans.test @@ -0,0 +1,200 @@ +# +# BUG#47863 +# This test verifies if the session variable 'binlog_format' and +# 'binlog_direct_non_transactional_updates' are read-only inside +# a transaction and in sub-statements. +# + +source include/have_innodb.inc; +source include/have_binlog_format_row.inc; + +set @save_binlog_format= @@global.binlog_format; +set @save_binlog_dirct= @@global.binlog_direct_non_transactional_updates; +create table t1 (a int) engine= myisam; +create table t2 (a int) engine= innodb; + +SELECT @@session.binlog_format; +SELECT @@session.binlog_direct_non_transactional_updates; +SELECT @@session.sql_log_bin; +SET AUTOCOMMIT=1; +--echo # Test that the session variable 'binlog_format', +--echo # 'binlog_direct_non_transactional_updates' and 'sql_log_bin' +--echo # are writable outside a transaction. +--echo # Current session values are ROW, FALSE, TRUE, respectively. +set @@session.binlog_format= statement; +set @@session.binlog_direct_non_transactional_updates= TRUE; +set @@session.sql_log_bin= FALSE; +SELECT @@session.binlog_format; +SELECT @@session.binlog_direct_non_transactional_updates; +SELECT @@session.sql_log_bin; + +begin; +--echo # Test that the session variable 'binlog_format', +--echo # 'binlog_direct_non_transactional_updates' and 'sql_log_bin' are +--echo # read-only inside a transaction with no preceding updates. +--echo # Current session values are STATEMENT, TRUE, FALSE, respectively. +--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT + set @@session.binlog_format= mixed; +--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT + set @@session.binlog_direct_non_transactional_updates= FALSE; +--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SQL_LOG_BIN +set @@session.sql_log_bin= FALSE; + + insert into t2 values (1); +--echo # Test that the session variable 'binlog_format', +--echo # 'binlog_direct_non_transactional_updates' and 'sql_log_bin' are +--echo # read-only inside a transaction with preceding transactional updates. +--echo # Current session values are STATEMENT, TRUE and FALSE, respectively. +--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT + set @@session.binlog_format= row; +--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT + set @@session.binlog_direct_non_transactional_updates= FALSE; +--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SQL_LOG_BIN +set @@session.sql_log_bin= FALSE; +commit; + +begin; + insert into t1 values (2); +--echo # Test that the session variable 'binlog_format' +--echo # 'binlog_direct_non_transactional_updates' and 'sql_log_bin' are +--echo # read-only inside a transaction with preceding non-transactional updates. +--echo # Current session values are STATEMENT, TRUE, FALSE, respectively. +--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT + set @@session.binlog_format= mixed; +--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT + set @@session.binlog_direct_non_transactional_updates= FALSE; +--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SQL_LOG_BIN +set @@session.sql_log_bin= FALSE; +commit; + +--echo # Test that the session variable 'binlog_format', +--echo # 'binlog_direct_non_transactional_updates' and 'sql_log_bin' are +--echo # writable when AUTOCOMMIT=0, before a transaction has started. +--echo # Current session values are STATEMENT, TRUE, FALSE, respectively. +set AUTOCOMMIT=0; +set @@session.binlog_format= row; +set @@session.binlog_direct_non_transactional_updates= FALSE; +set @@session.sql_log_bin= TRUE; +SELECT @@session.binlog_format; +SELECT @@session.binlog_direct_non_transactional_updates; +SELECT @@session.sql_log_bin; + +insert into t1 values (3); +--echo # Test that the session variable 'binlog_format', +--echo # 'binlog_direct_non_transactional_updates' and 'sql_log_bin' are +--echo # read-only inside an AUTOCOMMIT=0 transaction +--echo # with preceding non-transactional updates. +--echo # Current session values are ROW, FALSE, TRUE, respectively. +--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT +set @@session.binlog_format= statement; +--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT +set @@session.binlog_direct_non_transactional_updates= TRUE; +--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SQL_LOG_BIN +set @@session.sql_log_bin= FALSE; +SELECT @@session.binlog_format; +SELECT @@session.binlog_direct_non_transactional_updates; +SELECT @@session.sql_log_bin; +commit; + +insert into t2 values (4); +--echo # Test that the session variable 'binlog_format', +--echo # 'binlog_direct_non_transactional_updates' and 'sql_log_bin' are +--echo # read-only inside an AUTOCOMMIT=0 transaction with +--echo # preceding transactional updates. +--echo # Current session values are ROW, FALSE, TRUE, respectively. +--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT +set @@session.binlog_format= statement; +--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT +set @@session.binlog_direct_non_transactional_updates= TRUE; +--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SQL_LOG_BIN +set @@session.sql_log_bin= FALSE; +SELECT @@session.binlog_format; +SELECT @@session.binlog_direct_non_transactional_updates; +SELECT @@session.sql_log_bin; +commit; + +begin; + insert into t2 values (5); +--echo # Test that the global variable 'binlog_format' and +--echo # 'binlog_direct_non_transactional_updates' are +--echo # writable inside a transaction. +--echo # Current session values are ROW, FALSE, TRUE respectively. + SELECT @@global.binlog_format; + set @@global.binlog_format= statement; + set @@global.binlog_direct_non_transactional_updates= TRUE; + SELECT @@global.binlog_format; + SELECT @@global.binlog_direct_non_transactional_updates; +commit; + +set @@global.binlog_format= @save_binlog_format; +set @@global.binlog_direct_non_transactional_updates= @save_binlog_dirct; + +create table t3(a int, b int) engine= innodb; +create table t4(a int) engine= innodb; +create table t5(a int) engine= innodb; +delimiter |; +eval create trigger tr1 after insert on t3 for each row begin + insert into t4(a) values(1); + set @@session.binlog_format= statement; + insert into t4(a) values(2); + insert into t5(a) values(3); +end | +delimiter ;| + +--echo # Test that the session variable 'binlog_format' is read-only +--echo # in sub-statements. +--echo # Current session value is ROW. +--error ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT +insert into t3(a,b) values(1,1); +SELECT @@session.binlog_format; + +create table t6(a int, b int) engine= innodb; +create table t7(a int) engine= innodb; +create table t8(a int) engine= innodb; +delimiter |; +eval create trigger tr2 after insert on t6 for each row begin + insert into t7(a) values(1); + set @@session.binlog_direct_non_transactional_updates= TRUE; + insert into t7(a) values(2); + insert into t8(a) values(3); +end | +delimiter ;| + +--echo # Test that the session variable +--echo # 'binlog_direct_non_transactional_updates' is +--echo # read-only in sub-statements. +--echo # Current session value is FALSE. +--error ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_DIRECT +insert into t6(a,b) values(1,1); +SELECT @@session.binlog_direct_non_transactional_updates; + +create table t9(a int, b int) engine= innodb; +create table t10(a int) engine= innodb; +create table t11(a int) engine= innodb; +delimiter |; +eval create trigger tr3 after insert on t9 for each row begin + insert into t10(a) values(1); + set @@session.sql_log_bin= TRUE; + insert into t10(a) values(2); + insert into t11(a) values(3); +end | +delimiter ;| + +--echo # Test that the session variable 'sql_log_bin' is +--echo # read-only in sub-statements. +--echo # Current session value is FALSE. +--error ER_STORED_FUNCTION_PREVENTS_SWITCH_SQL_LOG_BIN +insert into t9(a,b) values(1,1); +SELECT @@session.sql_log_bin; + +drop table t1; +drop table t2; +drop table t3; +drop table t4; +drop table t5; +drop table t6; +drop table t7; +drop table t8; +drop table t9; +drop table t10; +drop table t11; diff --git a/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata.test b/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata.test new file mode 100644 index 00000000..4577c6c1 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata.test @@ -0,0 +1,334 @@ +################################################################################ +# WL#4618 RBR: extended table metadata in the binary log +# +# Below metadata is logged into Table_map_log_event +# - signedness of numeric columns +# - charsets of character columns +# - column names +# - set/enum character sets and string values +# - primary key +# +# The first two are always logged. The others are controlled by system +# variable --binlog-row-metadata +# +# The test will verify if the metadata can be logged and printed by mysqlbinlog +# correctly. +# mysqlbinlog --print-table-metadata will print the extra metadata +################################################################################ +--source include/have_debug.inc +--source include/have_binlog_format_row.inc + +RESET MASTER; +SET GLOBAL binlog_row_metadata = MINIMAL; + +--let $MYSQLD_DATADIR= `select @@datadir` +--let $binlog_file= $MYSQLD_DATADIR/master-bin.000001 + +--echo # +--echo # Temporal types can be printed correctly +--echo # +CREATE TABLE t1(c_year YEAR, c_date DATE, c_time TIME, c_time_f TIME(3), + c_datetime DATETIME, c_datetime_f DATETIME(3), + c_timestamp TIMESTAMP NOT NULL DEFAULT NOW(), + c_timestamp_f TIMESTAMP(3) DEFAULT "2017-1-1 10:10:10"); + +INSERT INTO t1(c_year) VALUES(2017); +--source include/print_optional_metadata.inc + +DROP TABLE t1; +RESET MASTER; + +--echo # +--echo # Geometry types can be printed correctly +--echo # +CREATE TABLE t1 (c_geo GEOMETRY, c_point POINT, c_linestring LINESTRING, + c_polygon POLYGON, c_multi_point MULTIPOINT, + c_multi_linestring MULTILINESTRING, c_multi_polygon MULTIPOLYGON, + c_geometrycollection GEOMETRYCOLLECTION, c_char CHAR(100)); + +INSERT INTO t1(c_point) VALUES(ST_PointFromText('POINT(10 10)')); +--source include/print_optional_metadata.inc + +RESET MASTER; +SET GLOBAL binlog_row_metadata = FULL; + +# geometry type is binlogged, the real geometry types are printed +INSERT INTO t1(c_point) VALUES(ST_PointFromText('POINT(10 10)')); +--source include/print_optional_metadata.inc + +DROP TABLE t1; +RESET MASTER; + +--echo # +--echo # Numeric types can be printed correctly +--echo # +CREATE TABLE t1(c_bit BIT(10), c_bool BOOL, c_smallint SMALLINT, + c_mediumint MEDIUMINT, c_int INT UNSIGNED, c_bigint BIGINT, + c_float FLOAT UNSIGNED, c_double DOUBLE, c_decimal DECIMAL(10, 2)); + +SET GLOBAL binlog_row_metadata = MINIMAL; +INSERT INTO t1(c_bool) VALUES(1); + +--echo # UNSIGNED flag should be printed +--source include/print_optional_metadata.inc + +RESET MASTER; +SET GLOBAL binlog_row_metadata = FULL; +INSERT INTO t1(c_bool) VALUES(1); + +--source include/print_optional_metadata.inc + +DROP TABLE t1; +RESET MASTER; + +--echo # +--echo # Character types can be printed correctly +--echo # +CREATE TABLE t1(c_char CHAR(10), c_varchar VARCHAR(500), + c_tinytext TINYTEXT, c_text TEXT, + c_mediumtext MEDIUMTEXT, c_longtext LONGTEXT CHARSET utf8); + +SET GLOBAL binlog_row_metadata = MINIMAL; +INSERT INTO t1(c_char) VALUES("1"); + +# Charset set is printed with default charset +--source include/print_optional_metadata.inc + +RESET MASTER; +SET GLOBAL binlog_row_metadata = FULL; +INSERT INTO t1(c_char) VALUES("1"); + +--source include/print_optional_metadata.inc + +DROP TABLE t1; +RESET MASTER; + +--echo # +--echo # Column names with non-ascii characters and escape characters can be printed correctly +--echo # +set names utf8; +CREATE TABLE t1(`åäö表\a'``"` INT); + +SHOW CREATE TABLE t1; + +INSERT INTO t1 VALUES(1); +--source include/print_optional_metadata.inc +DROP TABLE t1; +RESET MASTER; +--echo # +--echo # Charsets can be printed correctly +--echo # +CREATE TABLE t1(c_char_utf8 CHAR(10) CHARSET utf8, + c_varchar_utf8 VARCHAR(10) CHARSET utf8, + c_text_utf8 TEXT CHARSET utf8); + +INSERT INTO t1 VALUES("1", "2", "3"); + +# Charset set is printed with Default charset +--source include/print_optional_metadata.inc + +DROP TABLE t1; +RESET MASTER; + +# Test collation number less than 250 and collation number greater than 250 +CREATE TABLE t1(c_utf8mb4_520 CHAR(10) CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci, + c_utf8mb4_0900 VARCHAR(10) CHARSET utf8mb4 COLLATE utf8mb4_polish_ci, + c_utf8mb4_def TEXT CHARSET utf8mb4); + +INSERT INTO t1 VALUES("1", "2", "3"); + +# Charset set is printed without default charset +--source include/print_optional_metadata.inc + +DROP TABLE t1; +RESET MASTER; + +--echo # +--echo # Blob and binary columns can be printed correctly +--echo # +CREATE TABLE t1(c_binary BINARY(10), c_varbinary VARBINARY(10), + c_tinyblob TINYBLOB, c_blob BLOB, + c_mediumblob MEDIUMBLOB, c_longblob LONGBLOB); + +INSERT INTO t1 VALUES("1", "2", "3", "4", "5", "6"); +--source include/print_optional_metadata.inc + +DROP TABLE t1; +RESET MASTER; + +--echo # +--echo # Verify that SET string values and character sets can be printed correctly +--echo # + +set names utf8; +CREATE TABLE t1( + c_set_1 SET("set1_v1_å", "set1_v2_ä", "set1_v3_ö"), + c_set_2 SET("set2_v1_å", "set2_v2_ä", "set2_v3_ö") CHARACTER SET latin1, + c_set_4 SET("set3_v1_å", "set3_v2_ä", "set3_v3_ö") CHARACTER SET swe7 COLLATE swe7_bin); + +SET GLOBAL binlog_row_metadata = MINIMAL; +INSERT INTO t1 VALUES("set1_v1_å", "set2_v3_ö", "set3_v1_å"); +--source include/print_optional_metadata.inc + +RESET MASTER; +SET GLOBAL binlog_row_metadata = FULL; +INSERT INTO t1 VALUES("set1_v1_å", "set2_v3_ö", "set3_v1_å"); +--source include/print_optional_metadata.inc + +DROP TABLE t1; +RESET MASTER; + +--echo # +--echo # Verify that ENUM string values and character sets can be printed correctly +--echo # + +CREATE TABLE t1( + c_enum_1 ENUM("enum1_v1_å", "enum1_v2_ä", "enum1_v3_ö"), + c_enum_3 ENUM("enum2_v1_å", "enum2_v2_ä", "enum2_v3_ö") CHARACTER SET latin1, + c_enum_4 ENUM("enum3_v1_å", "enum3_v2_ä", "enum3_v3_ö") CHARACTER SET swe7 COLLATE swe7_bin); + +SET GLOBAL binlog_row_metadata = MINIMAL; +INSERT INTO t1 VALUES("enum1_v1_å", "enum2_v3_ö", "enum3_v1_å"); +--source include/print_optional_metadata.inc + +RESET MASTER; +SET GLOBAL binlog_row_metadata = FULL; +INSERT INTO t1 VALUES("enum1_v1_å", "enum2_v3_ö", "enum3_v1_å"); +--source include/print_optional_metadata.inc + +DROP TABLE t1; +RESET MASTER; + +--echo # +--echo # Verify that explicit NOT NULL can be printed correctly +--echo # +CREATE TABLE t1(c_not_null1 INT NOT NULL, c_null1 INT, c_not_null2 INT NOT NULL, + c_null2 INT); + +INSERT INTO t1 VALUES(1, 2, 3, 4); +--source include/print_optional_metadata.inc + +DROP TABLE t1; +RESET MASTER; + +--echo # +--echo # Verify that primary key can be printed correctly +--echo # +CREATE TABLE t1(c_key1 INT, c_key3 INT, c_not_key INT, c_key2 INT, +PRIMARY KEY(c_key1, c_key2, c_key3)); + +INSERT INTO t1 VALUES(1, 2, 3, 4); +--let $print_primary_key= 1 +--source include/print_optional_metadata.inc + +DROP TABLE t1; +RESET MASTER; + +# Key has prefix +CREATE TABLE t1(c_key1 CHAR(100), c_key3 CHAR(100), c_not_key INT, c_key2 CHAR(10), +PRIMARY KEY(c_key1(5), c_key2, c_key3(10))); + +INSERT INTO t1 VALUES("1", "2", 3, "4"); +--source include/print_optional_metadata.inc + +RESET MASTER; +# Primary key should not be printed +SET GLOBAL binlog_row_metadata = MINIMAL; + +INSERT INTO t1 VALUES("2", "2", 3, "4"); +--source include/print_optional_metadata.inc + +RESET MASTER; +--echo # +--echo # Coverage test: Print column index instead of column name if column name +--echo # is not binlogged. +--echo # +SET GLOBAL binlog_row_metadata = FULL; + +SET SESSION debug_dbug = 'd, dont_log_column_name'; +INSERT INTO t1 VALUES("3", "2", 3, "4"); +--source include/print_optional_metadata.inc + +--let $print_primary_key= +DROP TABLE t1; +RESET MASTER; + +--echo # +--echo # Coverage test: Inject an invalid column type +--echo # +CREATE TABLE t1(c1 int, c2 BLOB); + +SET SESSION debug_dbug = 'd,inject_invalid_column_type'; +INSERT INTO t1 VALUES(1, "a"); +# It prints an error +--source include/print_optional_metadata.inc + +RESET MASTER; + +--echo # +--echo # Coverage test: Inject an invalid BLOB metadata +--echo # +--let $start_pos= query_get_value(SHOW MASTER STATUS, Position, 1) + +SET SESSION debug_dbug = 'd,inject_invalid_blob_size'; +INSERT INTO t1 VALUES(2, "b"); + +# The invalid metadata will case assertion failure on Write_rows_log_event +# So we need to stop mysqlbinlog before reading Write_rows_log_event. +--let $stop_position= query_get_value(SHOW BINLOG EVENTS FROM $start_pos LIMIT 3, End_log_pos, 3) +--source include/print_optional_metadata.inc + +--echo # +--echo # Coverage test: Inject an invalid Geometry type +--echo # +DROP TABLE t1; +CREATE TABLE t1(c_geometry GEOMETRY, c_point POINT, c_multilinestring MULTILINESTRING); +RESET MASTER; +--let $start_pos= query_get_value(SHOW MASTER STATUS, Position, 1) + +SET SESSION debug_dbug = 'd,inject_invalid_geometry_type'; +INSERT INTO t1(c_point) VALUES(ST_PointFromText('POINT(10 10)')); + +# The invalid metadata will case assertion failure on Write_rows_log_event +# So we need to stop mysqlbinlog before reading Write_rows_log_event. +--let $stop_position= query_get_value(SHOW BINLOG EVENTS FROM $start_pos LIMIT 3, End_log_pos, 3) +--source include/print_optional_metadata.inc + +DROP TABLE t1; +RESET MASTER; +--echo # +--echo # Comptibility Test: Verify mysqlbinlog can print OLD table_map_log_event +--echo # without any optional metadata +--echo # +CREATE TABLE t1(c_int INT, c_tiny_int_unsigned TINYINT UNSIGNED, + c_binary BINARY(10), c_text TEXT, c_point POINT); + +SET session debug_dbug='d,simulate_no_optional_metadata'; +INSERT INTO t1(c_int) VALUES(1); +# TINYINT will be printed without UNSIGNED flag, +# CHAR will be printed as BINARY(10) +# POINT will be printed as GEOMETRY +--let $stop_position= +--source include/print_optional_metadata.inc + +DROP TABLE t1; +RESET MASTER; +--echo # +--echo # Simulate error on initializing charset and primary key metadata +--echo # +CREATE TABLE t1(c1 char(10) PRIMARY KEY); + +SET session debug_dbug='d,simulate_init_charset_field_error'; +INSERT INTO t1 VALUES("a"); + +SET GLOBAL binlog_row_metadata = FULL; +SET session debug_dbug='d,simulate_init_primary_key_field_error'; +INSERT INTO t1 VALUES("b"); + +--let $print_primary_key= 1 +--source include/print_optional_metadata.inc + +SET SESSION debug_dbug = ''; +SET GLOBAL binlog_row_metadata = NO_LOG; +DROP TABLE t1; +RESET MASTER; diff --git a/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_binary.test b/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_binary.test new file mode 100644 index 00000000..29e10ede --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_binary.test @@ -0,0 +1,74 @@ +################################################################################ +# WL#4618 RBR: extended table metadata in the binary log +# +# Below metadata is logged into Table_map_log_event +# - signedness of numeric columns +# - charsets of character columns +# - column names +# - set/enum character sets and string values +# - primary key +# +# The first two are always logged. The others are controlled by system +# variable --binlog-row-metadata +# +# The test will verify if the metadata can be logged and printed by mysqlbinlog +# correctly. +# mysqlbinlog --print-table-metadata will print the extra metadata +################################################################################ +--source include/have_debug.inc +--source include/have_binlog_format_row.inc +--let $MYSQLD_DATADIR= `select @@datadir` +--let $binlog_file= $MYSQLD_DATADIR/master-bin.000001 + +RESET MASTER; +--echo # +--echo # Verify that SET string values and character sets can be printed correctly +--echo # + +SET NAMES utf8; +CREATE TABLE t1( + c_set_1 SET("set1_v1_å", "set1_v2_ä", "set1_v3_ö"), + c_set_2 SET("set2_v1_å", "set2_v2_ä", "set2_v3_ö") CHARACTER SET binary); + +SET GLOBAL binlog_row_metadata = MINIMAL; +INSERT INTO t1 VALUES("set1_v1_å", "set2_v2_ä"); +--source include/print_optional_metadata.inc + +RESET MASTER; +SET GLOBAL binlog_row_metadata = FULL; +INSERT INTO t1 VALUES("set1_v1_å", "set2_v2_ä"); +--source include/print_optional_metadata.inc +INSERT INTO t1 VALUES("set1_v3_ö", "set2_v3_ö"); +INSERT INTO t1 VALUES("set1_v1_å", "set2_v1_å"); +SELECT c_set_1, HEX(c_set_1) FROM t1; +SELECT c_set_2, HEX(c_set_2) FROM t1; + +DROP TABLE t1; +RESET MASTER; + +--echo # +--echo # Verify that ENUM string values and character sets can be printed correctly +--echo # + +CREATE TABLE t1( + c_enum_1 ENUM("enum1_v1_å", "enum1_v2_ä", "enum1_v3_ö"), + c_enum_2 ENUM("enum2_v1_å", "enum2_v2_ä", "enum2_v3_ö") CHARACTER SET binary); + +SET GLOBAL binlog_row_metadata = MINIMAL; +INSERT INTO t1 VALUES("enum1_v1_å", "enum2_v2_ä"); +--source include/print_optional_metadata.inc + + +RESET MASTER; +SET GLOBAL binlog_row_metadata = FULL; +INSERT INTO t1 VALUES("enum1_v1_å", "enum2_v2_ä"); +--source include/print_optional_metadata.inc +INSERT INTO t1 VALUES("enum1_v3_ö", "enum2_v3_ö"); +INSERT INTO t1 VALUES("enum1_v1_å", "enum2_v1_å"); +SELECT c_enum_1, HEX(c_enum_1) FROM t1; +SELECT c_enum_2, HEX(c_enum_2) FROM t1; + +DROP TABLE t1; +RESET MASTER; + +SET GLOBAL binlog_row_metadata = NO_LOG; diff --git a/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_ucs2.test b/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_ucs2.test new file mode 100644 index 00000000..8c9e2242 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_ucs2.test @@ -0,0 +1,75 @@ +################################################################################ +# WL#4618 RBR: extended table metadata in the binary log +# +# Below metadata is logged into Table_map_log_event +# - signedness of numeric columns +# - charsets of character columns +# - column names +# - set/enum character sets and string values +# - primary key +# +# The first two are always logged. The others are controlled by system +# variable --binlog-row-metadata +# +# The test will verify if the metadata can be logged and printed by mysqlbinlog +# correctly. +# mysqlbinlog --print-table-metadata will print the extra metadata +################################################################################ +--source include/have_debug.inc +--source include/have_binlog_format_row.inc +--source include/have_ucs2.inc +--let $MYSQLD_DATADIR= `select @@datadir` +--let $binlog_file= $MYSQLD_DATADIR/master-bin.000001 + +RESET MASTER; +--echo # +--echo # Verify that SET string values and character sets can be printed correctly +--echo # + +SET NAMES utf8; +CREATE TABLE t1( + c_set_1 SET("set1_v1_å", "set1_v2_ä", "set1_v3_ö"), + c_set_2 SET("set2_v1_å", "set2_v2_ä", "set2_v3_ö") CHARACTER SET ucs2); + +SET GLOBAL binlog_row_metadata = MINIMAL; +INSERT INTO t1 VALUES("set1_v1_å", "set2_v2_ä"); +--source include/print_optional_metadata.inc + +RESET MASTER; +SET GLOBAL binlog_row_metadata = FULL; +INSERT INTO t1 VALUES("set1_v1_å", "set2_v2_ä"); +--source include/print_optional_metadata.inc +INSERT INTO t1 VALUES("set1_v3_ö", "set2_v3_ö"); +INSERT INTO t1 VALUES("set1_v1_å", "set2_v1_å"); +SELECT c_set_1, HEX(c_set_1) FROM t1; +SELECT c_set_2, HEX(c_set_2) FROM t1; + +DROP TABLE t1; +RESET MASTER; + +--echo # +--echo # Verify that ENUM string values and character sets can be printed correctly +--echo # + +CREATE TABLE t1( + c_enum_1 ENUM("enum1_v1_å", "enum1_v2_ä", "enum1_v3_ö"), + c_enum_2 ENUM("enum2_v1_å", "enum2_v2_ä", "enum2_v3_ö") CHARACTER SET ucs2); + +SET GLOBAL binlog_row_metadata = MINIMAL; +INSERT INTO t1 VALUES("enum1_v1_å", "enum2_v2_ä"); +--source include/print_optional_metadata.inc + + +RESET MASTER; +SET GLOBAL binlog_row_metadata = FULL; +INSERT INTO t1 VALUES("enum1_v1_å", "enum2_v2_ä"); +--source include/print_optional_metadata.inc +INSERT INTO t1 VALUES("enum1_v3_ö", "enum2_v3_ö"); +INSERT INTO t1 VALUES("enum1_v1_å", "enum2_v1_å"); +SELECT c_enum_1, HEX(c_enum_1) FROM t1; +SELECT c_enum_2, HEX(c_enum_2) FROM t1; + +DROP TABLE t1; +RESET MASTER; + +SET GLOBAL binlog_row_metadata = NO_LOG; diff --git a/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_utf32.test b/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_utf32.test new file mode 100644 index 00000000..094de058 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_table_map_optional_metadata_utf32.test @@ -0,0 +1,75 @@ +################################################################################ +# WL#4618 RBR: extended table metadata in the binary log +# +# Below metadata is logged into Table_map_log_event +# - signedness of numeric columns +# - charsets of character columns +# - column names +# - set/enum character sets and string values +# - primary key +# +# The first two are always logged. The others are controlled by system +# variable --binlog-row-metadata +# +# The test will verify if the metadata can be logged and printed by mysqlbinlog +# correctly. +# mysqlbinlog --print-table-metadata will print the extra metadata +################################################################################ +--source include/have_debug.inc +--source include/have_binlog_format_row.inc +--source include/have_utf32.inc +--let $MYSQLD_DATADIR= `select @@datadir` +--let $binlog_file= $MYSQLD_DATADIR/master-bin.000001 + +RESET MASTER; +--echo # +--echo # Verify that SET string values and character sets can be printed correctly +--echo # + +SET NAMES utf8; +CREATE TABLE t1( + c_set_1 SET("set1_v1_å", "set1_v2_ä", "set1_v3_ö"), + c_set_2 SET("set2_v1_å", "set2_v2_ä", "set2_v3_ö") CHARACTER SET utf32); + +SET GLOBAL binlog_row_metadata = MINIMAL; +INSERT INTO t1 VALUES("set1_v1_å", "set2_v2_ä"); +--source include/print_optional_metadata.inc + +RESET MASTER; +SET GLOBAL binlog_row_metadata = FULL; +INSERT INTO t1 VALUES("set1_v1_å", "set2_v2_ä"); +--source include/print_optional_metadata.inc +INSERT INTO t1 VALUES("set1_v3_ö", "set2_v3_ö"); +INSERT INTO t1 VALUES("set1_v1_å", "set2_v1_å"); +SELECT c_set_1, HEX(c_set_1) FROM t1; +SELECT c_set_2, HEX(c_set_2) FROM t1; + +DROP TABLE t1; +RESET MASTER; + +--echo # +--echo # Verify that ENUM string values and character sets can be printed correctly +--echo # + +CREATE TABLE t1( + c_enum_1 ENUM("enum1_v1_å", "enum1_v2_ä", "enum1_v3_ö"), + c_enum_2 ENUM("enum2_v1_å", "enum2_v2_ä", "enum2_v3_ö") CHARACTER SET utf32); + +SET GLOBAL binlog_row_metadata = MINIMAL; +INSERT INTO t1 VALUES("enum1_v1_å", "enum2_v2_ä"); +--source include/print_optional_metadata.inc + + +RESET MASTER; +SET GLOBAL binlog_row_metadata = FULL; +INSERT INTO t1 VALUES("enum1_v1_å", "enum2_v2_ä"); +--source include/print_optional_metadata.inc +INSERT INTO t1 VALUES("enum1_v3_ö", "enum2_v3_ö"); +INSERT INTO t1 VALUES("enum1_v1_å", "enum2_v1_å"); +SELECT c_enum_1, HEX(c_enum_1) FROM t1; +SELECT c_enum_2, HEX(c_enum_2) FROM t1; + +DROP TABLE t1; +RESET MASTER; + +SET GLOBAL binlog_row_metadata = NO_LOG; diff --git a/mysql-test/suite/binlog/t/binlog_tmp_table.test b/mysql-test/suite/binlog/t/binlog_tmp_table.test new file mode 100644 index 00000000..45428530 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_tmp_table.test @@ -0,0 +1,159 @@ +# ==== Purpose ==== +# +# Test if statements used temporary tables are binlogged correctly +# +# ==== Method ==== +# +# Use two connections, use temporary tables on both of them, and by +# switching connections between statements, the test can check if the +# statements are logged with the correct thread id. +# +# The statements current tested include: +# CREATE TEMPORARY TABLE +# CREATE TEMPORARY TABLE LIKE +# INSERT +# REPLACE +# UPDATE +# INSERT SELECT +# TRUNCATE +# +# Note: When adding new query statements, please add them between the +# two 'flush logs'. And aslo please make sure the connection is +# switched between each statement. +# +# ==== Related bugs ==== +# +# BUG#35583 mysqlbinlog replay fails with ERROR 1146 when temp tables are used +# +source include/have_log_bin.inc; +source include/have_binlog_format_mixed_or_statement.inc; + +RESET MASTER; + +--disable_query_log +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +--enable_query_log + +connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,); +connect (master1,127.0.0.1,root,,test,$MASTER_MYPORT,); + +create table foo (a int); + +flush logs; + +connection master; +create temporary table tmp1_foo like foo; +connection master1; +create temporary table tmp2_foo (a int); + +connection master; +insert into tmp1_foo values (1), (2), (3), (4); +connection master1; +replace into tmp2_foo values (1), (2), (3), (4); + +connection master; +update tmp1_foo set a=2*a-1; +connection master1; +update tmp2_foo set a=2*a; + +connection master; +delete from tmp1_foo where a < 5; +connection master1; +delete from tmp2_foo where a < 5; + +--disable_warnings +connection master; +insert into foo select * from tmp1_foo; +connection master1; +insert into foo select * from tmp2_foo; +--enable_warnings + +connection master; +truncate table tmp1_foo; +connection master1; +truncate table tmp2_foo; + +let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1); + +flush logs; + +connection default; +select * from foo; + +# prepare for the replay +drop table foo; +create table foo (a int); + +# replay from binary log +let $MYSQLD_DATADIR= `select @@datadir`; +exec $MYSQL_BINLOG $MYSQLD_DATADIR/$binlog_file | $MYSQL; +select * from foo; + +# clean up +drop table foo; + +################################################################# +# BUG#51226 +################################################################# + +RESET MASTER; + +-- let $dbname=b51226 + +connect (con1,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); +connect (con2,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); + +# +# action: on con1 create the database and the tmp table +# +-- connection con1 +-- eval create database $dbname +-- eval use $dbname +create temporary table t1(i int); + +# +# action: on con1 create the tmp table +# +-- connection con2 +-- eval use $dbname +create temporary table t1(i int); + +# action: at this point, the last event binlogged contains the +# pseudo_thread_id from con2. So now we switch to con1, issue +# a statement that fails and close the connection (which logs +# implicitely a DROP TEMPORARY TABLE). +# +# Before the patch this would not log con1's pseudo_thread_id +# because the failing statement would reset THD context +# (unsetting the thread_specific_used flag, and consequently, +# causing the DROP event to be logged without pseudo_thread_id +# in its header). + +-- connection con1 +-- error 1050 +create temporary table t1(i int); +-- disconnect con1 + +-- connection default +-- let $wait_binlog_event= DROP +-- source include/wait_for_binlog_event.inc + +# action: insert in the t1. This would cause the the test to fail, +# because when replaying the binlog the previous implicit drop +# temp table would have been executed under the wrong +# pseudo_thread_id, dropping the tmp table on con2. +-- connection con2 +insert into t1 values(1); +-- disconnect con2 + +-- connection default +-- let $wait_binlog_event= DROP +-- source include/wait_for_binlog_event.inc + +-- eval DROP DATABASE $dbname +FLUSH LOGS; + +# assertion: assert that when replaying the binary log will succeed, +# instead of failing with "Table 'XXX.YYY' doesn't exist" +-- let $MYSQLD_DATADIR= `select @@datadir` +-- exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 | $MYSQL diff --git a/mysql-test/suite/binlog/t/binlog_tmp_table_row.test b/mysql-test/suite/binlog/t/binlog_tmp_table_row.test new file mode 100644 index 00000000..ce11c880 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_tmp_table_row.test @@ -0,0 +1,30 @@ +# ==== Purpose ==== +# +# Test if statements used temporary tables are not binlogged in the case of +# binlog_format=row +# +# ==== Method ==== +# +# We will see if binlog file size is increased or not, It should be constant for the +# entire period of test. +# +# ==== Related bugs ==== +# +# Mdev-9266 +# +source include/have_log_bin.inc; +source include/have_binlog_format_row.inc; + +RESET MASTER; + +--echo #Create table test +--let $sql_query= create temporary table t1(a int, b int) +--source suite/binlog/include/check_binlog_size.inc + +--echo #Add index test +--let $sql_query= create index index_a on t1(a) +--source suite/binlog/include/check_binlog_size.inc + +--echo #drop index test +--let $sql_query= drop index index_a on t1 +--source suite/binlog/include/check_binlog_size.inc diff --git a/mysql-test/suite/binlog/t/binlog_trigger.test b/mysql-test/suite/binlog/t/binlog_trigger.test new file mode 100644 index 00000000..3f93d6e8 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_trigger.test @@ -0,0 +1,51 @@ +--source include/not_embedded.inc +--source include/have_binlog_format_statement.inc + +--disable_query_log +reset master; # get rid of previous tests binlog +--enable_query_log + +--echo # +--echo # WL#3253: multiple triggers per table +--echo # + +--echo # Testing that the FOLLOWS and PRECEDES clauses get logged + +CREATE TABLE t1 (a INT, b INT); +CREATE TRIGGER tr1_bi BEFORE INSERT ON t1 FOR EACH ROW INSERT INTO t2 (a) VALUES (NEW.a + 100); +CREATE TRIGGER tr4_bi BEFORE INSERT ON t1 FOR EACH ROW INSERT INTO t2 (a) VALUES (NEW.a + 300); +CREATE TRIGGER tr2_bi BEFORE INSERT ON t1 FOR EACH ROW FOLLOWS tr1_bi INSERT INTO t2 (a) VALUES (NEW.a + 200); +CREATE TRIGGER tr3_bi BEFORE INSERT ON t1 FOR EACH ROW precedes tr4_bi INSERT INTO t2 (a) VALUES (NEW.a + 400); +DROP TABLE t1; + + +--let $binlog_file = LAST +source include/show_binlog_events.inc; + +--echo # +--echo # MDEV-25517 Atomic DDL: Assertion `query_arg' in THD::binlog_query +--echo # upon DROP TRIGGER +--echo # + +# This test case is 'random' by design. For most cases the second DROP TRIGGER +# will generate a warning "Dropped orphan trigger...", but if there is a timing +# issue, we may get another error or warning later. This is ok as it enables +# us to have more code paths tested over time. + +CREATE TABLE t1 (a INT); +CREATE TRIGGER trg AFTER INSERT ON t1 FOR EACH ROW SET @x = 1; +--disable_warnings +--connect (con1,localhost,root,,test) +--send + DROP TRIGGER trg; +--connection default +--error 0,ER_TRG_DOES_NOT_EXIST +DROP TRIGGER trg; +# Cleanup +--connection con1 +--error 0,ER_TRG_DOES_NOT_EXIST +--reap +--disconnect con1 +--connection default +--enable_warnings +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/binlog_truncate_active_log.inc b/mysql-test/suite/binlog/t/binlog_truncate_active_log.inc new file mode 100644 index 00000000..68ac7527 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_truncate_active_log.inc @@ -0,0 +1,70 @@ +connect(master1,localhost,root,,); +connect(master2,localhost,root,,); +connect(master3,localhost,root,,); +connect(master4,localhost,root,,); + +--connection default + +# First to commit few transactions +INSERT INTO t VALUES (10); +INSERT INTO tm VALUES (10); + +--connection master1 +# Hold insert after write to binlog and before "run_commit_ordered" in engine +SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL master1_ready WAIT_FOR signal_never_arrives"; +--send_eval $query1 + +--connection master2 +SET DEBUG_SYNC= "now WAIT_FOR master1_ready"; +SET DEBUG_SYNC= "commit_before_get_LOCK_after_binlog_sync SIGNAL master2_ready"; +--send_eval $query2 + +--connection master3 +SET DEBUG_SYNC= "now WAIT_FOR master2_ready"; +SELECT @@global.gtid_binlog_pos as 'Before the crash'; + +--connection master4 +# Simulate prepared & not-logged trx; it will never recover. +SET DEBUG_SYNC= "ha_commit_trans_before_log_and_order SIGNAL master4_ready WAIT_FOR signal_never_arrives"; +--send INSERT INTO t4 VALUES (13) + +--connection master3 +SET DEBUG_SYNC= "now WAIT_FOR master4_ready"; +SELECT @@global.gtid_binlog_pos as 'Before the crash and never logged trx'; + +--connection default +--source include/kill_mysqld.inc +--disconnect master1 +--disconnect master2 +--disconnect master3 +--disconnect master4 + +# +# Server restart +# +--let $restart_parameters= --rpl-semi-sync-slave-enabled=1 --sync-binlog=1 --log-warnings=3 +--source include/start_mysqld.inc + +# Check error log for a successful truncate message. +--let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.1.err + +--let SEARCH_FILE=$log_error_ +--let SEARCH_PATTERN=Successfully truncated.*to remove transactions starting from GTID $truncate_gtid_pos + +--source include/search_pattern_in_file.inc + +--echo Pre-crash binlog file content: +--let $binlog_file= query_get_value(show binary logs, Log_name, $binlog_file_index) +--source include/show_binlog_events.inc + +SELECT @@global.gtid_binlog_pos as 'After the crash'; +--echo "One row should be present in table 't'" +SELECT * FROM t; +--echo "No row should be present in table 't4'" +SELECT * FROM t4; + +# prepare binlog file index for the next test +--inc $binlog_file_index + +# Local cleanup +DELETE FROM t; diff --git a/mysql-test/suite/binlog/t/binlog_truncate_active_log.test b/mysql-test/suite/binlog/t/binlog_truncate_active_log.test new file mode 100644 index 00000000..7c63a853 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_truncate_active_log.test @@ -0,0 +1,104 @@ +# ==== Purpose ==== +# +# Test verifies the truncation of single binary log file. +# +# ==== References ==== +# +# MDEV-21117: recovery for --rpl-semi-sync-slave-enabled server + +--source include/have_innodb.inc +--source include/have_aria.inc +# File: binlog_truncate_active_log.inc included in test makes use of +# 'debug_sync' facility. +--source include/have_debug_sync.inc +--source include/have_binlog_format_statement.inc + +call mtr.add_suppression("Can.t init tc log"); +call mtr.add_suppression("Aborting"); + +# The following cases are tested: +# A. 2pc transaction is followed by a blank "zero-engines" one +# B. 2pc transaction follows the blank one +# C. Similarly to A, with the XA blank transaction + +RESET MASTER; +SET @@global.sync_binlog=1; +CREATE TABLE t (f INT) ENGINE=INNODB; +CREATE TABLE t2 (f INT) ENGINE=INNODB; +CREATE TABLE t4 (f INT) ENGINE=INNODB; +CREATE TABLE tm (f INT) ENGINE=Aria; + +# Old (pre-crash) binlog file index initial value. +# It keeps incremented at the end of each case. +--let $binlog_file_index=1 + +--echo # Case A. +# Using 'debug_sync' hold 'query1' execution after 'query1' is flushed and +# synced to binary log but not yet committed. In an another connection hold +# 'query2' execution after 'query2' is flushed and synced to binlog. +# Crash and restart server with --rpl-semi-sync-slave-enabled=1 +# +# During recovery of binary log 'query1' status is checked with InnoDB engine, +# it will be in prepared but not yet commited. All transactions starting from +# 'query1' onwards will be removed from the binary log. +# Show-binlog-events is to prove that. + +--let $truncate_gtid_pos = 0-1-7 +--let $query1 = INSERT INTO t VALUES (20) +--let $query2 = DELETE FROM t2 WHERE f = 0 /* no such record */ +--source binlog_truncate_active_log.inc + +--echo # Case B. +# The inverted sequence ends up to truncate starting from $query2 +--let $truncate_gtid_pos = 0-1-11 +--let $query1 = DELETE FROM t2 WHERE f = 0 +--let $query2 = INSERT INTO t VALUES (20) +--source binlog_truncate_active_log.inc + + +--echo # Case C. +delimiter |; +CREATE PROCEDURE sp_blank_xa() +BEGIN + XA START 'blank'; + DELETE FROM t2 WHERE f = 0 /* no such record */; + XA END 'blank'; + XA PREPARE 'blank'; +END| +delimiter ;| + +# The same as in A with $query2 being the zero-engine XA transaction. +# Both $query1 and $query2 are going to be truncated. +--let $truncate_gtid_pos = 0-1-15 +--let $query1 = INSERT INTO t VALUES (20) +--let $query2 = CALL sp_blank_xa +--source binlog_truncate_active_log.inc + +DROP PROCEDURE sp_blank_xa; + + +--echo # Case D. +delimiter |; +CREATE PROCEDURE sp_xa() +BEGIN + XA START 'xid'; + DELETE FROM t WHERE f = 10; + XA END 'xid'; + XA PREPARE 'xid'; +END| +delimiter ;| + +# The same as in B with $query1 being the prepared XA transaction. +# Truncation must occurs at $query2. +--let $truncate_gtid_pos = 0-1-21 +--let $query1 = CALL sp_xa +--let $query2 = INSERT INTO t2 VALUES (20) +--source binlog_truncate_active_log.inc + +DROP PROCEDURE sp_xa; + + +--echo # Cleanup +DROP TABLE t,t2,tm; +SET @@global.sync_binlog= default; +--echo # End of the tests diff --git a/mysql-test/suite/binlog/t/binlog_truncate_innodb.test b/mysql-test/suite/binlog/t/binlog_truncate_innodb.test new file mode 100644 index 00000000..511b82bd --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_truncate_innodb.test @@ -0,0 +1,45 @@ +source include/have_log_bin.inc; +source include/have_innodb.inc; + +let $engine = InnoDB; + +SET @old_binlog_format=@@binlog_format; + +SET BINLOG_FORMAT=ROW; +RESET MASTER; + +source include/binlog_truncate.test; + +--echo # Even though the isolation level might be permissive, truncate +--echo # table follows a stricter isolation as its locking is based on +--echo # (exclusive) metadata locks. + +let $before_truncate = SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +source include/binlog_truncate.test; + +let $before_truncate = SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +source include/binlog_truncate.test; + +let $before_truncate = SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; +source include/binlog_truncate.test; + +let $before_truncate = SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +source include/binlog_truncate.test; + +SET BINLOG_FORMAT=STATEMENT; +RESET MASTER; + +source include/binlog_truncate.test; + +--echo # Truncate is not supported for SBR if the isolation level is +--echo # READ UNCOMMITTED or READ COMMITTED. These specific isolation +--echo # levels are tested elsewhere. + +let $before_truncate = SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; +source include/binlog_truncate.test; + +let $before_truncate = SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +source include/binlog_truncate.test; + +SET @@global.binlog_format = @old_binlog_format; +SET @@session.binlog_format = @old_binlog_format;
\ No newline at end of file diff --git a/mysql-test/suite/binlog/t/binlog_truncate_kill.test b/mysql-test/suite/binlog/t/binlog_truncate_kill.test new file mode 100644 index 00000000..0b9e873d --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_truncate_kill.test @@ -0,0 +1,55 @@ +############################################################################### +# Bug#17942050:KILL OF TRUNCATE TABLE WILL LEAD TO BINARY LOG WRITTEN WHILE +# ROWS REMAINS +# +# Problem: +# ======== +# When truncate table fails while using transactional based engines even +# though the operation errors out we still continue and log it to binlog. +# Because of this master has data but the truncate will be written to binary +# log which will cause inconsistency. +# +# Test: +# ===== +# Make master to wait in "open_table" call during the execution of truncate +# table command and kill the truncate table from other connection. This causes +# open table to return an error saying truncate failed during open table. This +# statement should not be binlogged. +############################################################################### +--source include/have_innodb.inc +--source include/have_debug_sync.inc +--source include/have_binlog_format_statement.inc +RESET MASTER; +--connection default +CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY, a INT, b INT) ENGINE=INNODB; +INSERT INTO t1(a, b) VALUES(1,2),(2,4),(3,6),(4,8),(5,10); +SET DEBUG_SYNC = "open_and_process_table signal truncate_before_lock wait_for forever"; +--send TRUNCATE t1 + +connect(con1,localhost,root,,); +SET DEBUG_SYNC = "now wait_for truncate_before_lock"; +# Wait for one connection to reach open_and_process_table. +--let $show_statement= SHOW PROCESSLIST +--let $field= State +--let $condition= 'debug sync point: open_and_process_table'; +--source include/wait_show_condition.inc + +SELECT ((@id := id) - id) FROM information_schema.processlist WHERE processlist.info LIKE '%TRUNCATE t1%' AND state LIKE '%open_and_process_table%'; +# Test killing from mysql server +KILL QUERY @id; + +connection default; +--ERROR ER_QUERY_INTERRUPTED +--reap + +connection con1; +--source include/show_binlog_events.inc + +disconnect con1; +--source include/wait_until_disconnected.inc +connection default; + +SELECT * FROM t1; + +DROP TABLE t1; +SET DEBUG_SYNC= 'RESET'; diff --git a/mysql-test/suite/binlog/t/binlog_truncate_multi_engine.inc b/mysql-test/suite/binlog/t/binlog_truncate_multi_engine.inc new file mode 100644 index 00000000..f3801070 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_truncate_multi_engine.inc @@ -0,0 +1,75 @@ +# +# Invoked by binlog_truncate_multi_engine.test +# Parameters: +# $debug_sync_action describes debug-sync actions +# $kill_server 1 when to crash, 0 for regular restart +# $restart_parameters the caller may simulate partial commit at recovery +# $test_outcome summary of extected results +# $MYSQLD_DATADIR + +--echo # +--echo # +--echo # Case $case : $description +--echo # +RESET MASTER; +FLUSH LOGS; +SET GLOBAL max_binlog_size= 4096; + +connect(con1,localhost,root,,); +--echo List of binary logs before rotation +--source include/show_binary_logs.inc +INSERT INTO t1 VALUES (1, REPEAT("x", 1)); +INSERT INTO t2 VALUES (1, REPEAT("x", 1)); +--let $is_case_B=`SELECT $case = "B"` + +if ($is_case_B) +{ + --write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait-binlog_truncate_multi_engine.test +EOF + + SET GLOBAL debug_dbug="d,enable_log_write_upto_crash"; +} +BEGIN; + INSERT INTO t2 VALUES (2, REPEAT("x", 4100)); + INSERT INTO t1 VALUES (2, REPEAT("x", 4100)); + +if (`SELECT $debug_sync_action != ""`) +{ + --eval SET DEBUG_SYNC= $debug_sync_action +} +send COMMIT; + +--connection default +if ($is_case_B) +{ + --source include/wait_until_disconnected.inc + --source include/start_mysqld.inc +} +if (!$is_case_B) +{ + SET DEBUG_SYNC= "now WAIT_FOR con1_ready"; + --echo List of binary logs after rotation + --source include/show_binary_logs.inc + + --echo # restart the server with $restart_parameters + --echo # the server is restarted + --source include/restart_mysqld.inc +} + +--connection default +--echo # +--echo # *** Summary: $test_outcome: +--echo # +SELECT COUNT(*) FROM t1; +SELECT COUNT(*) FROM t2; +SELECT @@GLOBAL.gtid_binlog_state; +SELECT @@GLOBAL.gtid_binlog_pos; +--echo List of binary logs at the end of the tests +--source include/show_binary_logs.inc +--echo # *** +# cleanup +DELETE FROM t1; +DELETE FROM t2; +--disconnect con1 +--echo # diff --git a/mysql-test/suite/binlog/t/binlog_truncate_multi_engine.opt b/mysql-test/suite/binlog/t/binlog_truncate_multi_engine.opt new file mode 100644 index 00000000..03e7d74f --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_truncate_multi_engine.opt @@ -0,0 +1 @@ +--plugin-load=$HA_ROCKSDB_SO diff --git a/mysql-test/suite/binlog/t/binlog_truncate_multi_engine.test b/mysql-test/suite/binlog/t/binlog_truncate_multi_engine.test new file mode 100644 index 00000000..12b0a743 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_truncate_multi_engine.test @@ -0,0 +1,59 @@ +# ==== Purpose ==== +# +# Test verifies truncation of multiple binary logs with multiple transactional +# storage engines +# +# ==== References ==== +# +# MDEV-21117: recovery for --rpl-semi-sync-slave-enabled server + +--source include/have_rocksdb.inc +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/have_binlog_format_row.inc + +--let $old_max_binlog_size= `select @@global.max_binlog_size` +call mtr.add_suppression("Can.t init tc log"); +call mtr.add_suppression("Aborting"); +--let $MYSQLD_DATADIR= `SELECT @@datadir` + +SET @@global.sync_binlog= 1; +CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb; +CREATE TABLE t2 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=rocksdb; + +--let $case = "A" +--let $description = "neither engine committed => rollback & binlog truncate" +# Hold off engine commits after write to binlog and its rotation. +# The transaction is killed along with the server after that. +--let $shutdown_timeout=0 +--let $debug_sync_action = "commit_after_release_LOCK_log SIGNAL con1_ready WAIT_FOR signal_no_signal" +--let $restart_parameters = --rpl-semi-sync-slave-enabled=1 --sync-binlog=1 +--let $test_outcome= 1 row should be present in both tables; binlog is truncated; number of binlogs at reconnect - 3 +--source binlog_truncate_multi_engine.inc +--echo Proof of the truncated binlog file is readable (two transactions must be seen): +--exec $MYSQL_BINLOG --short-form --skip-annotate-row-events $MYSQLD_DATADIR/master-bin.000002 + +--let $case = "B" +--let $description = "one engine has committed its transaction branch" +# Hold off after one engine has committed. +--let $shutdown_timeout=0 +--let $debug_sync_action = "" +# Both debug_sync and debug-dbug are required to make sure Engines remember the commit state +# debug_sync alone will not help. +--let $restart_parameters = --rpl-semi-sync-slave-enabled=1 --sync-binlog=1 +--let $test_outcome= 2 rows should be present in both tables; no binlog truncation; one extra binlog file compare with A; number of binlogs at reconnect - 4 +--source binlog_truncate_multi_engine.inc + +--let $case = "C" +--let $description= "both engines have committed its transaction branch" +--let $debug_sync_action = "commit_after_run_commit_ordered SIGNAL con1_ready" +# Hold off after both engines have committed. The server is shut down. +--let $shutdown_timeout= +--let $restart_parameters = --rpl-semi-sync-slave-enabled=1 --sync-binlog=1 +--let $test_outcome= 2 rows should be present in both tables; no binlog truncation; the same # of binlog files as in B; number of binlogs at reconnect - 4 +--source binlog_truncate_multi_engine.inc + +DROP TABLE t1, t2; +SET @@global.sync_binlog= default; +--echo # End of the tests diff --git a/mysql-test/suite/binlog/t/binlog_truncate_multi_log.test b/mysql-test/suite/binlog/t/binlog_truncate_multi_log.test new file mode 100644 index 00000000..079c79b2 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_truncate_multi_log.test @@ -0,0 +1,87 @@ +# ==== Purpose ==== +# +# Test verifies truncation of multiple binary logs. +# +# ==== References ==== +# MDEV-21117: recovery for --rpl-semi-sync-slave-enabled server + +--source include/have_innodb.inc +--source include/have_debug_sync.inc +--source include/have_binlog_format_row.inc + +call mtr.add_suppression("Can.t init tc log"); +call mtr.add_suppression("Aborting"); + +SET @@global.max_binlog_size= 4096; +SET @@global.sync_binlog= 1; +RESET MASTER; +FLUSH LOGS; +CREATE TABLE ti (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb; +CREATE TABLE tm (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=MyISAM; + +connect(master1,localhost,root,,); +--echo "List of binary logs before rotation" +--source include/show_binary_logs.inc + +# Some load to either non- and transactional egines +# that should not affect the following recovery: +INSERT INTO ti VALUES(1,"I am gonna survive"); +INSERT INTO tm VALUES(1,"me too!"); + +# hold on near engine commit +SET DEBUG_SYNC= "commit_after_release_LOCK_after_binlog_sync SIGNAL master1_ready WAIT_FOR master1_go_never_arrives"; +--send INSERT INTO ti VALUES (2, REPEAT("x", 4100)) + +connect(master2,localhost,root,,); +# The 2nd trx for recovery, it does not rotate binlog +SET DEBUG_SYNC= "now WAIT_FOR master1_ready"; +SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL master2_ready WAIT_FOR master2_go_never_arrives"; +--send INSERT INTO ti VALUES (3, "not gonna survive") + +--connection default +SET DEBUG_SYNC= "now WAIT_FOR master2_ready"; + +connect(master3,localhost,root,,); +# The 3nd trx for recovery, it won't get into binlog nor therefore recover +SET DEBUG_SYNC= "ha_commit_trans_before_log_and_order SIGNAL master3_ready WAIT_FOR master3_go_never_arrives"; +--send INSERT INTO ti VALUES (4, "not gonna be log therefore survive"),(5, "ditto") + +--connection default +SET DEBUG_SYNC= "now WAIT_FOR master3_ready"; + +--echo "List of binary logs before crash" +--source include/show_binary_logs.inc +--echo # The gtid binlog state prior the crash will be truncated at the end of the test +SELECT @@global.gtid_binlog_state; + +--connection default +--source include/kill_mysqld.inc +--disconnect master1 +--disconnect master2 +--disconnect master3 + +# +# Server restart +# +--let $restart_parameters= --rpl-semi-sync-slave-enabled=1 --sync-binlog=1 --log-warnings=3 +--source include/start_mysqld.inc + +# Check error log for a successful truncate message. +let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.1.err; + +--let SEARCH_FILE=$log_error_ +--let SEARCH_PATTERN=truncated binlog file:.*master.*000002 +--source include/search_pattern_in_file.inc + + +--echo "One record should be present in table" +SELECT * FROM ti; + +--echo # The truncated gtid binlog state +SELECT @@global.gtid_binlog_state; +SELECT @@global.gtid_binlog_pos; + +--echo # Cleanup +DROP TABLE ti; +SET @@global.sync_binlog= default; +--echo # End of the tests diff --git a/mysql-test/suite/binlog/t/binlog_truncate_multi_log_unsafe.test b/mysql-test/suite/binlog/t/binlog_truncate_multi_log_unsafe.test new file mode 100644 index 00000000..5a5cc667 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_truncate_multi_log_unsafe.test @@ -0,0 +1,120 @@ +# ==== Purpose ==== +# The test verifies attempt to recover by the semisync slave server whose +# binlog is unsafe for truncation. +# +# ==== Implementation ==== +# 2 binlog files are created with the 1st one destined to be the binlog +# checkpoint file for recovery. +# The final group of events is replication unsafe (myisam INSERT). +# Therefore the semisync slave recovery may not. +# +# Steps: +# 0 - Set max_binlog_size= 4096, to help an insert into a +# transaction table 'ti' get binlog rotated while the +# transaction won't be committed, being stopped at +# a prior to commit debug_sync point +# 1 - insert into a non-transactional 'tm' table completes with +# binary logging as well +# 2 - kill and attempt to restart the server as semisync slave that +# must produce an expected unsafe-to-recover error +# 3 - complete the test with a normal restart that successfully finds and +# commits the transaction in doubt. +# +# ==== References ==== +# +# MDEV-21117: recovery for --rpl-semi-sync-slave-enabled server +# + +--source include/have_innodb.inc +--source include/have_debug_sync.inc +--source include/have_binlog_format_row.inc + +SET @@global.max_binlog_size= 4096; + +call mtr.add_suppression("Table '.*tm' is marked as crashed and should be repaired"); +call mtr.add_suppression("Got an error from unknown thread"); +call mtr.add_suppression("Checking table: '.*tm'"); +call mtr.add_suppression("Recovering table: '.*tm'"); +call mtr.add_suppression("Cannot truncate the binary log to file"); +call mtr.add_suppression("Crash recovery failed"); +call mtr.add_suppression("Can.t init tc log"); +call mtr.add_suppression("Aborting"); +call mtr.add_suppression("Found 1 prepared transactions"); +call mtr.add_suppression("mysqld: Table.*tm.*is marked as crashed"); +call mtr.add_suppression("Checking table.*tm"); + +RESET MASTER; +FLUSH LOGS; +SET @@global.sync_binlog=1; +CREATE TABLE ti (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb; +CREATE TABLE tm (f INT) ENGINE=MYISAM; + +--let $row_count = 5 +--let $i = `select $row_count-2` +--disable_query_log +while ($i) +{ + --eval INSERT INTO ti VALUES ($i, REPEAT("x", 1)) + --dec $i +} +--enable_query_log +INSERT INTO tm VALUES(1); + +connect(master1,localhost,root,,); +connect(master2,localhost,root,,); +connect(master3,localhost,root,,); + +--connection master1 + +# The 1st trx binlogs, rotate binlog and hold on before committing at engine +SET DEBUG_SYNC= "commit_after_release_LOCK_after_binlog_sync SIGNAL master1_ready WAIT_FOR master1_go_never_arrives"; +--send_eval INSERT INTO ti VALUES ($row_count - 1, REPEAT("x", 4100)) + +--connection master2 +SET DEBUG_SYNC= "now WAIT_FOR master1_ready"; +# The 2nd trx for recovery, it does not rotate binlog +SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL master2_ready WAIT_FOR master2_go_never_arrives"; +--send_eval INSERT INTO ti VALUES ($row_count, REPEAT("x", 1)) + +--connection master3 +SET DEBUG_SYNC= "now WAIT_FOR master2_ready"; +SET DEBUG_SYNC= "commit_before_get_LOCK_after_binlog_sync SIGNAL master3_ready"; +--send INSERT INTO tm VALUES (2) + +--connection default +SET DEBUG_SYNC= "now WAIT_FOR master3_ready"; +--echo # The gtid binlog state prior the crash must be restored at the end of the test; +SELECT @@global.gtid_binlog_state; +--source include/kill_mysqld.inc + +# +# Server restarts +# +--echo # Failed restart as the semisync slave +--error 1 +--exec $MYSQLD_LAST_CMD --rpl-semi-sync-slave-enabled=1 >> $MYSQLTEST_VARDIR/log/mysqld.1.err 2>&1 + +--echo # Normal restart +--source include/start_mysqld.inc + +# Check error log for correct messages. +let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.1.err; + +--let SEARCH_FILE=$log_error_ +--let SEARCH_PATTERN=Cannot truncate the binary log to file +--source include/search_pattern_in_file.inc + +--echo # Proof that the in-doubt transactions are recovered by the 2nd normal server restart +--eval SELECT COUNT(*) = $row_count as 'True' FROM ti +# myisam table may require repair (which is not tested here) +--disable_warnings +SELECT COUNT(*) <= 1 FROM tm; +--enable_warnings + +--echo # The gtid binlog state prior the crash is restored now +SELECT @@GLOBAL.gtid_binlog_state; +SELECT @@GLOBAL.gtid_binlog_pos; + +--echo # Cleanup +DROP TABLE ti, tm; +--echo End of test diff --git a/mysql-test/suite/binlog/t/binlog_truncate_myisam.test b/mysql-test/suite/binlog/t/binlog_truncate_myisam.test new file mode 100644 index 00000000..864e9c63 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_truncate_myisam.test @@ -0,0 +1,17 @@ +source include/have_log_bin.inc; + +SET @old_binlog_format=@@binlog_format; + +let $engine = MyISAM; + +SET BINLOG_FORMAT=ROW; +RESET MASTER; + +source include/binlog_truncate.test; + +SET BINLOG_FORMAT=STATEMENT; +RESET MASTER; + +source include/binlog_truncate.test; + +SET BINLOG_FORMAT=@old_binlog_format; diff --git a/mysql-test/suite/binlog/t/binlog_unsafe-master.opt b/mysql-test/suite/binlog/t/binlog_unsafe-master.opt new file mode 100644 index 00000000..50fc48d2 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_unsafe-master.opt @@ -0,0 +1 @@ +--log-output=file,table diff --git a/mysql-test/suite/binlog/t/binlog_unsafe.test b/mysql-test/suite/binlog/t/binlog_unsafe.test new file mode 100644 index 00000000..b637a980 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_unsafe.test @@ -0,0 +1,762 @@ +# ==== Background ==== +# +# Some statements may execute differently on master and slave when +# logged in statement format. Such statements are called unsafe. +# Unsafe statements include: +# +# - statements using @@variables (with a small number of exceptions; +# see below); +# - statements using certain functions, e.g., UUID(); +# - statements using LIMIT; +# - INSERT DELAYED; +# - insert into two autoinc columns; +# - statements using UDF's. +# - statements reading from log tables in the mysql database. +# - INSERT ... SELECT ... ON DUPLICATE KEY UPDATE +# - REPLACE ... SELECT +# - CREATE TABLE [IGNORE/REPLACE] SELECT +# - INSERT IGNORE...SELECT +# - UPDATE IGNORE +# - INSERT... ON DUPLICATE KEY UPDATE on a table with two UNIQUE KEYS +# +# Note that statements that use stored functions, stored procedures, +# triggers, views, or prepared statements that invoke unsafe +# statements shall also be unsafe. +# +# Unsafeness of a statement shall have the following consequences: +# +# 1. If the binlogging is on and the unsafe statement is logged: +# - If binlog_format=STATEMENT, the statement shall give a warning. +# - If binlog_format=MIXED or binlog_format=ROW, the statement shall +# be logged in row format. +# +# 2. If binlogging is off or the statement is not logged (e.g. SELECT +# UUID()), no warning shall be issued and the statement shall not +# be logged. +# +# Moreover, when a sub-statement of a recursive construct (i.e., +# stored function, stored procedure, trigger, view, or prepared +# statement) is unsafe and binlog_format=STATEMENT, then a warning +# shall be issued for every recursive construct. In effect, this +# creates a stack trace from the top-level statement to the unsafe +# statement. +# +# +# ==== Purpose ==== +# +# This test verifies that a warning is generated when it should, +# according to the rules above. +# +# All @@variables should be unsafe, with some exceptions. Therefore, +# this test also verifies that the exceptions do *not* generate a +# warning. +# +# +# ==== Method ==== +# +# 1. Each type of statements listed above is executed. +# +# 2. Each unsafe statement is wrapped in each type of recursive +# construct (stored function, stored procedure, trigger, view, or +# prepared statement). +# +# 3. Each unsafe statement is wrapped in two levels of recursive +# constructs (function invoking trigger invoking UUID(), etc). +# +# We try to insert the variables that should not be unsafe into a +# table, and verify that *no* warning is issued. +# +# Execute a unsafe statement calling a trigger or stored function +# or neither when SQL_LOG_BIN is turned ON, a warning/error should be issued +# Execute a unsafe statement calling a trigger or stored function +# or neither when @@SQL_LOG_BIN is turned OFF, +# no warning/error is issued +# +# +# ==== Related bugs and worklogs ==== +# +# WL#3339: Issue warnings when statement-based replication may fail +# BUG#31168: @@hostname does not replicate +# BUG#34732: mysqlbinlog does not print default values for auto_increment variables +# BUG#34768: nondeterministic INSERT using LIMIT logged in stmt mode if binlog_format=mixed +# BUG#41980, SBL, INSERT .. SELECT .. LIMIT = ERROR, even when @@SQL_LOG_BIN is 0 +# BUG#42640: mysqld crashes when unsafe statements are executed (STRICT_TRANS_TABLES mode) +# BUG#45825: INSERT DELAYED is not unsafe: logged in statement format +# BUG#45785: LIMIT in SP does not cause RBL if binlog_format=MIXED +# BUG#47995: Mark user functions as unsafe +# BUG#49222: Mark RAND() unsafe +# BUG#11758262: MARK INSERT...SEL...ON DUP KEY UPD,REPLACE...SEL,CREATE...[IGN|REPL] SEL +# +# ==== Related test cases ==== +# +# rpl.rpl_variables verifies that variables which cannot be replicated +# safely in statement mode are replicated correctly in mixed or row +# mode. +# +# rpl.rpl_variables_stm tests the small subset of variables that +# actually can be replicated safely in statement mode. +# +--source include/have_udf.inc +--source include/have_log_bin.inc +--source include/have_binlog_format_statement.inc + +--disable_query_log +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +--enable_query_log + +--echo #### Setup tables #### + +CREATE TABLE t0 (a CHAR(200)); +CREATE TABLE t1 (a CHAR(200)); +CREATE TABLE t2 (a CHAR(200)); +CREATE TABLE t3 (a CHAR(200)); +CREATE TABLE ta0 (a CHAR(200)); +CREATE TABLE ta1 (a CHAR(200)); +CREATE TABLE ta2 (a CHAR(200)); +CREATE TABLE ta3 (a CHAR(200)); +CREATE TABLE autoinc_table (a INT PRIMARY KEY AUTO_INCREMENT); +CREATE TABLE data_table (a CHAR(200)); +INSERT INTO data_table VALUES ('foo'); +CREATE TABLE trigger_table_1 (a INT); +CREATE TABLE trigger_table_2 (a INT); +CREATE TABLE trigger_table_3 (a INT); +CREATE TABLE double_autoinc_table (a INT PRIMARY KEY AUTO_INCREMENT); + +--DELIMITER | +CREATE TRIGGER double_autoinc_trig +BEFORE INSERT ON double_autoinc_table FOR EACH ROW +BEGIN + INSERT INTO autoinc_table VALUES (NULL); +END| + +CREATE FUNCTION multi_unsafe_func() RETURNS INT +BEGIN + INSERT INTO t0 VALUES(CONCAT(@@hostname, @@hostname)); + INSERT INTO t0 VALUES(0); + INSERT INTO t0 VALUES(CONCAT(UUID(), @@hostname)); + RETURN 1; +END| +--DELIMITER ; + +--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB +--eval CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "$UDF_EXAMPLE_SO" + +# In each iteration of this loop, we select one method to make the +# statement unsafe. +--let $unsafe_type= 0 +while ($unsafe_type < 9) { + + --echo + + if ($unsafe_type == 0) { + --echo ==== Testing UUID() unsafeness ==== + --let $desc_0= unsafe UUID() function + --let $stmt_sidef_0= INSERT INTO t0 VALUES (UUID()) + --let $value_0= UUID() + --let $sel_sidef_0= + --let $sel_retval_0= SELECT UUID() + --let $CRC_ARG_expected_number_of_warnings= 1 + } + + if ($unsafe_type == 1) { + --echo ==== Testing @@hostname unsafeness ==== + --let $desc_0= unsafe @@hostname variable + --let $stmt_sidef_0= INSERT INTO t0 VALUES (@@hostname) + --let $value_0= @@hostname + --let $sel_sidef_0= + # $sel_retval is going to be used in views. Views cannot execute + # statements that refer to @@variables. Hence, we set $set_retval + # to empty instead of SELECT @@hostname. + --let $sel_retval_0= + --let $CRC_ARG_expected_number_of_warnings= 1 + } + + if ($unsafe_type == 2) { + --echo ==== Testing SELECT...LIMIT unsafeness ==== + --let $desc_0= unsafe SELECT...LIMIT statement + --let $stmt_sidef_0= INSERT INTO t0 SELECT * FROM data_table LIMIT 1 + --let $value_0= + --let $sel_sidef_0= + --let $sel_retval_0= SELECT * FROM data_table LIMIT 1 + --let $CRC_ARG_expected_number_of_warnings= 1 + } + + if ($unsafe_type == 3) { + --echo ==== Testing INSERT DELAYED safeness after BUG#54579 is fixed ==== + --let $desc_0= unsafe INSERT DELAYED statement + --let $stmt_sidef_0= INSERT DELAYED INTO t0 VALUES (1), (2) + --let $value_0= + --let $sel_sidef_0= + --let $sel_retval_0= + --let $CRC_ARG_expected_number_of_warnings= 0 + } + + if ($unsafe_type == 4) { + --echo ==== Testing unsafeness of insert of two autoinc values ==== + --let $desc_0= unsafe update of two autoinc columns + --let $stmt_sidef_0= INSERT INTO double_autoinc_table VALUES (NULL) + --let $value_0= + --let $sel_sidef_0= + --let $sel_retval_0= + --let $CRC_ARG_expected_number_of_warnings= 1 + } + + if ($unsafe_type == 5) { + --echo ==== Testing unsafeness of UDF's ==== + --let $desc_0= unsafe UDF + --let $stmt_sidef_0= INSERT INTO t0 VALUES (myfunc_int(10)) + --let $value_0= myfunc_int(10) + --let $sel_sidef_0= SELECT myfunc_int(10) + --let $sel_retval_0= + --let $CRC_ARG_expected_number_of_warnings= 1 + } + + if ($unsafe_type == 6) { + --echo ==== Testing unsafeness of access to mysql.general_log ==== + --let $desc_0= unsafe use of mysql.general_log + --let $stmt_sidef_0= INSERT INTO t0 SELECT COUNT(*) FROM mysql.general_log + --let $value_0= + --let $sel_sidef_0= + --let $sel_retval_0= SELECT COUNT(*) FROM mysql.general_log + --let $CRC_ARG_expected_number_of_warnings= 1 + } + + if ($unsafe_type == 7) { + --echo ==== Testing a statement that is unsafe in many ways ==== + --let $desc_0= statement that is unsafe in many ways + # Concatenate three unsafe values, and then concatenate NULL to + # that so that the result is NULL and we instead use autoinc. + --let $stmt_sidef_0= INSERT DELAYED INTO double_autoinc_table SELECT CONCAT(UUID(), @@hostname, myfunc_int(), NULL) FROM mysql.general_log LIMIT 1 + --let $value_0= + --let $sel_sidef_0= + --let $sel_retval_0= + --let $CRC_ARG_expected_number_of_warnings= 7 + } + + if ($unsafe_type == 8) { + --echo ==== Testing a statement that is unsafe several times ==== + --let $desc_0= statement that is unsafe several times + --let $stmt_sidef_0= INSERT INTO ta0 VALUES (multi_unsafe_func()) + --let $value_0= + --let $sel_sidef_0= SELECT multi_unsafe_func() + --let $sel_retval_0= + --let $CRC_ARG_expected_number_of_warnings= 2 + } + + # In each iteration of the following loop, we select one way to + # enclose the unsafe statement as a sub-statement of a recursive + # construct (i.e., a function, procedure, trigger, view, or prepared + # statement). + # + # In the last iteration, $call_type_1=7, we don't create a recursive + # construct. Instead, we just invoke the unsafe statement directly. + + --let $call_type_1= 0 + while ($call_type_1 < 8) { + #--echo debug: level 1, types $call_type_1 -> $unsafe_type + --let $CRC_ARG_level= 1 + --let $CRC_ARG_type= $call_type_1 + --let $CRC_ARG_stmt_sidef= $stmt_sidef_0 + --let $CRC_ARG_value= $value_0 + --let $CRC_ARG_sel_sidef= $sel_sidef_0 + --let $CRC_ARG_sel_retval= $sel_retval_0 + --let $CRC_ARG_desc= $desc_0 + --source suite/rpl/include/create_recursive_construct.inc + --let $stmt_sidef_1= $CRC_RET_stmt_sidef + --let $value_1= $CRC_RET_value + --let $sel_sidef_1= $CRC_RET_sel_sidef + --let $sel_retval_1= $CRC_RET_sel_retval + --let $is_toplevel_1= $CRC_RET_is_toplevel + --let $drop_1= $CRC_RET_drop + --let $desc_1= $CRC_RET_desc + + # Some statements must be top-level statements, i.e., cannot be + # called as a sub-statement of any recursive construct. (One + # example is 'EXECUTE prepared_stmt'). When + # create_recursive_construct.inc creates a top-level statement, it + # sets $CRC_RET_is_toplevel=1. + + if (!$is_toplevel_1) { + + # In each iteration of this loop, we select one way to enclose + # the previous recursive construct in another recursive + # construct. + + --let $call_type_2= 0 + while ($call_type_2 < 7) { + #--echo debug: level 2, types $call_type_2 -> $call_type_1 -> $unsafe_type + --let $CRC_ARG_level= 2 + --let $CRC_ARG_type= $call_type_2 + --let $CRC_ARG_stmt_sidef= $stmt_sidef_1 + --let $CRC_ARG_value= $value_1 + --let $CRC_ARG_sel_sidef= $sel_sidef_1 + --let $CRC_ARG_sel_retval= $sel_retval_1 + --let $CRC_ARG_desc= $desc_1 + --source suite/rpl/include/create_recursive_construct.inc + --let $stmt_sidef_2= $CRC_RET_stmt_sidef + --let $value_2= $CRC_RET_value + --let $sel_sidef_2= $CRC_RET_sel_sidef + --let $sel_retval_2= $CRC_RET_sel_retval + --let $is_toplevel_2= $CRC_RET_is_toplevel + --let $drop_2= $CRC_RET_drop + --let $desc_2= $CRC_RET_desc + + if (!$is_toplevel_2) { + + # Conditioned out since it makes result file really big. + + if (0) { + + # In each iteration of this loop, we select one way to enclose + # the previous recursive construct in another recursive + # construct. + + --let $call_type_3= 0 + while ($call_type_3 < 7) { + #--echo debug: level 3, types $call_type_2 -> $call_type_2 -> $call_type_1 -> $unsafe_type + --let $CRC_ARG_level= 3 + --let $CRC_ARG_type= $call_type_3 + --let $CRC_ARG_stmt_sidef= $stmt_sidef_2 + --let $CRC_ARG_value= $value_2 + --let $CRC_ARG_sel_sidef= $sel_sidef_2 + --let $CRC_ARG_sel_retval= $sel_retval_2 + --let $CRC_ARG_desc= $desc_2 + --source suite/rpl/include/create_recursive_construct.inc + + # Drop created object. + if ($drop_3) { + --eval $drop_3 + } + --inc $call_type_3 + } # while (call_type_3) + } # if (0) + } # if (!is_toplevel_2) + + # Drop created object. + if ($drop_2) { + --eval $drop_2 + } + --inc $call_type_2 + } # while (call_type_2) + } # if (!is_toplevel_1) + + # Drop created object. + if ($drop_1) { + --eval $drop_1 + } + --inc $call_type_1 + } # while (call_type_1) + + --inc $unsafe_type +} # while (unsafe_type) + +DROP TRIGGER double_autoinc_trig; +DROP TABLE t0, t1, t2, t3, ta0, ta1, ta2, ta3, + autoinc_table, double_autoinc_table, + data_table, + trigger_table_1, trigger_table_2, trigger_table_3; +DROP FUNCTION myfunc_int; +DROP FUNCTION multi_unsafe_func; + + +--echo ==== Special system variables that should *not* be unsafe ==== + +CREATE TABLE t1 (a VARCHAR(1000)); +CREATE TABLE autoinc_table (a INT PRIMARY KEY AUTO_INCREMENT); + +INSERT INTO t1 VALUES (@@session.auto_increment_increment); +INSERT INTO t1 VALUES (@@session.auto_increment_offset); +INSERT INTO t1 VALUES (@@session.character_set_client); +INSERT INTO t1 VALUES (@@session.character_set_connection); +INSERT INTO t1 VALUES (@@session.character_set_database); +INSERT INTO t1 VALUES (@@session.character_set_server); +INSERT INTO t1 VALUES (@@session.collation_connection); +INSERT INTO t1 VALUES (@@session.collation_database); +INSERT INTO t1 VALUES (@@session.collation_server); +INSERT INTO t1 VALUES (@@session.foreign_key_checks); +INSERT INTO t1 VALUES (@@session.identity); +INSERT INTO t1 VALUES (@@session.last_insert_id); +INSERT INTO t1 VALUES (@@session.lc_time_names); +INSERT INTO t1 VALUES (@@session.pseudo_thread_id); +INSERT INTO t1 VALUES (@@session.sql_auto_is_null); +INSERT INTO t1 VALUES (@@session.timestamp); +INSERT INTO t1 VALUES (@@session.time_zone); +INSERT INTO t1 VALUES (@@session.unique_checks); + +SET @my_var= 4711; +INSERT INTO t1 VALUES (@my_var); + +# using insert_id implicitly should be ok. +SET insert_id= 12; +INSERT INTO autoinc_table VALUES (NULL); + +# See set_var.cc for explanation. +--echo The following variables *should* give a warning, despite they are replicated. +INSERT INTO t1 VALUES (@@session.sql_mode); +INSERT INTO t1 VALUES (@@session.insert_id); + + +DROP TABLE t1, autoinc_table; + + +# +# BUG#34768 - nondeterministic INSERT using LIMIT logged in stmt mode if +# binlog_format=mixed +# +CREATE TABLE t1(a INT, b INT, KEY(a), PRIMARY KEY(b)); +INSERT INTO t1 SELECT * FROM t1 LIMIT 1; +REPLACE INTO t1 SELECT * FROM t1 LIMIT 1; +UPDATE t1 SET a=1 LIMIT 1; +DELETE FROM t1 LIMIT 1; +delimiter |; +CREATE PROCEDURE p1() +BEGIN + INSERT INTO t1 SELECT * FROM t1 LIMIT 1; + REPLACE INTO t1 SELECT * FROM t1 LIMIT 1; + UPDATE t1 SET a=1 LIMIT 1; + DELETE FROM t1 LIMIT 1; +END| +delimiter ;| +CALL p1(); +DROP PROCEDURE p1; +DROP TABLE t1; + +# +# Bug#42634: % character in query can cause mysqld signal 11 segfault +# + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (a VARCHAR(200), b VARCHAR(200)); +INSERT INTO t1 VALUES ('a','b'); +UPDATE t1 SET b = '%s%s%s%s%s%s%s%s%s%s%s%s%s%s' WHERE a = 'a' LIMIT 1; +DROP TABLE t1; + +# +#For bug#41980, SBL, INSERT .. SELECT .. LIMIT = ERROR, even when @@SQL_LOG_BIN is 0 +# + +--disable_warnings +DROP TABLE IF EXISTS t1, t2; +--enable_warnings +CREATE TABLE t1(i INT PRIMARY KEY); +CREATE TABLE t2(i INT PRIMARY KEY); +CREATE TABLE t3(i INT, ch CHAR(50)); + +--echo "Should issue message Statement may not be safe to log in statement format." +INSERT INTO t1 SELECT * FROM t2 LIMIT 1; + +DELIMITER |; +CREATE FUNCTION func6() +RETURNS INT +BEGIN + INSERT INTO t1 VALUES (10); + INSERT INTO t1 VALUES (11); + INSERT INTO t1 VALUES (12); + RETURN 0; +END| +DELIMITER ;| +--echo "Should issue message Statement may not be safe to log in statement format only once" +INSERT INTO t3 VALUES(func6(), UUID()); + +--echo "Check whether SET @@SQL_LOG_BIN = 0/1 doesn't work in substatements" +DELIMITER |; +CREATE FUNCTION fun_check_log_bin() RETURNS INT +BEGIN + SET @@SQL_LOG_BIN = 0; + INSERT INTO t1 VALUES(@@global.sync_binlog); + RETURN 200; +END| +DELIMITER ;| +--echo "One unsafe warning should be issued in the following statement" +--error ER_STORED_FUNCTION_PREVENTS_SWITCH_SQL_LOG_BIN +SELECT fun_check_log_bin(); +--echo "SQL_LOG_BIN should be ON still" +SHOW VARIABLES LIKE "SQL_LOG_BIN"; + +set @save_log_bin = @@SESSION.SQL_LOG_BIN; +set @@SESSION.SQL_LOG_BIN = 0; +--echo "Should NOT have any warning message issued in the following statements" +INSERT INTO t1 SELECT * FROM t2 LIMIT 1; +DROP TABLE t1,t2; + +--echo "Should NOT have any warning message issued in the following func7() and trig" +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (a TEXT); +CREATE TABLE trigger_table (a CHAR(7)); +DELIMITER |; +CREATE FUNCTION func7() +RETURNS INT +BEGIN + INSERT INTO t1 VALUES (@@global.sync_binlog); + INSERT INTO t1 VALUES (@@session.insert_id); + INSERT INTO t2 SELECT UUID(); + INSERT INTO t2 VALUES (@@session.sql_mode); + INSERT INTO t2 VALUES (@@global.init_slave); + RETURN 0; +END| +DELIMITER ;| +SHOW VARIABLES LIKE "SQL_LOG_BIN"; +SELECT func7(); + +--echo ---- Insert from trigger ---- + +DELIMITER |; +CREATE TRIGGER trig +BEFORE INSERT ON trigger_table +FOR EACH ROW +BEGIN + INSERT INTO t1 VALUES (@@global.sync_binlog); + INSERT INTO t1 VALUES (@@session.insert_id); + INSERT INTO t1 VALUES (@@global.auto_increment_increment); + INSERT INTO t2 SELECT UUID(); + INSERT INTO t2 VALUES (@@session.sql_mode); + INSERT INTO t2 VALUES (@@global.init_slave); + INSERT INTO t2 VALUES (@@hostname); +END| +DELIMITER ;| + +INSERT INTO trigger_table VALUES ('bye.'); + +#clean up +DROP FUNCTION fun_check_log_bin; +DROP FUNCTION func6; +DROP FUNCTION func7; +DROP TRIGGER trig; +DROP TABLE t1, t2, t3, trigger_table; +set @@SESSION.SQL_LOG_BIN = @save_log_bin; + +# +# For BUG#42640: mysqld crashes when unsafe statements are executed (STRICT_TRANS_TABLES mode) +# +SET @save_sql_mode = @@SESSION.SQL_MODE; +SET @@SESSION.SQL_MODE = STRICT_ALL_TABLES; + +CREATE TABLE t1(i INT PRIMARY KEY); +CREATE TABLE t2(i INT PRIMARY KEY); + +INSERT INTO t1 SELECT * FROM t2 LIMIT 1; +INSERT INTO t1 VALUES(@@global.sync_binlog); + +UPDATE t1 SET i = 999 LIMIT 1; +DELETE FROM t1 LIMIT 1; + +DROP TABLE t1, t2; +SET @@SESSION.SQL_MODE = @save_sql_mode; + +# +# BUG#45825: INSERT DELAYED is not unsafe: logged in statement format +# BUG#45785: LIMIT in SP does not cause RBL if binlog_format=MIXED +# +SET @old_binlog_format = @@session.binlog_format; +SET binlog_format = MIXED; + +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (a INT); +INSERT INTO t2 VALUES (1), (2); + +--DELIMITER | +CREATE PROCEDURE proc_insert_delayed () +BEGIN + INSERT DELAYED INTO t1 VALUES (1), (2); +END| + +CREATE FUNCTION func_limit () +RETURNS INT +BEGIN + INSERT INTO t1 SELECT * FROM t2 LIMIT 1; + RETURN 1; +END| +--DELIMITER ; + +RESET MASTER; +CALL proc_insert_delayed(); +--disable_ps2_protocol +SELECT func_limit(); +--enable_ps2_protocol +source include/show_binlog_events.inc; + +SET @@session.binlog_format = @old_binlog_format; +DROP TABLE t1, t2; +DROP PROCEDURE proc_insert_delayed; +DROP FUNCTION func_limit; + +# +# BUG#45827 +# The test verifies if stmt that have more than one +# different tables to update with autoinc columns +# will produce unsafe warning +# + +# Test case1: stmt that have more than one different tables +# to update with autoinc columns should produce +# unsafe warning when calling a function +CREATE TABLE t1 (a INT, b INT PRIMARY KEY AUTO_INCREMENT); +CREATE TABLE t2 (a INT, b INT PRIMARY KEY AUTO_INCREMENT); + +# The purpose of this function is to insert into t1 so that the second +# column is auto_increment'ed. +DELIMITER |; +CREATE FUNCTION func_modify_t1 () +RETURNS INT +BEGIN + INSERT INTO t1 SET a = 1; + RETURN 0; +END| +DELIMITER ;| +--echo # The following statement causes auto-incrementation +--echo # of both t1 and t2. It is logged in statement format, +--echo # so it should produce unsafe warning. +INSERT INTO t2 SET a = func_modify_t1(); + +SET SESSION binlog_format = MIXED; +--echo # Check if the statement is logged in row format. +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +INSERT INTO t2 SET a = func_modify_t1(); +--source include/show_binlog_events.inc + +# clean up +DROP TABLE t1,t2; +DROP FUNCTION func_modify_t1; +# +# Test case2: stmt that have more than one different tables +# to update with autoinc columns should produce +# unsafe warning when invoking a trigger +SET SESSION binlog_format = STATEMENT; +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (a INT, b INT PRIMARY KEY AUTO_INCREMENT); +CREATE TABLE t3 (a INT, b INT PRIMARY KEY AUTO_INCREMENT); + +# The purpose of this function is to insert into t1 so that the second +# column is auto_increment'ed. +delimiter |; +create trigger tri_modify_two_tables before insert on t1 for each row begin + insert into t2(a) values(new.a); + insert into t3(a) values(new.a); +end | +delimiter ;| +--echo # The following statement causes auto-incrementation +--echo # of both t2 and t3. It is logged in statement format, +--echo # so it should produce unsafe warning +INSERT INTO t1 SET a = 1; + +SET SESSION binlog_format = MIXED; +--echo # Check if the statement is logged in row format. +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +INSERT INTO t1 SET a = 2; +--source include/show_binlog_events.inc + +# clean up +DROP TABLE t1,t2,t3; + +# +# BUG#47995: Mark user functions as unsafe +# BUG#49222: Mark RAND() unsafe +# +# Test that the system functions that are supposed to be marked unsafe +# generate a warning. Each INSERT statement below should generate a +# warning. +# +SET SESSION binlog_format = STATEMENT; + +CREATE TABLE t1 (a VARCHAR(1000)); +INSERT INTO t1 VALUES (CURRENT_USER()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (FOUND_ROWS()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (GET_LOCK('tmp', 1)); #marked unsafe in BUG#47995 +INSERT INTO t1 VALUES (IS_FREE_LOCK('tmp')); #marked unsafe in BUG#47995 +INSERT INTO t1 VALUES (IS_USED_LOCK('tmp')); #marked unsafe in BUG#47995 +INSERT INTO t1 VALUES (LOAD_FILE('../../std_data/words2.dat')); #marked unsafe in BUG#39701 +INSERT INTO t1 VALUES (MASTER_POS_WAIT('dummy arg', 4711, 1)); +INSERT INTO t1 VALUES (RELEASE_LOCK('tmp')); #marked unsafe in BUG#47995 +INSERT INTO t1 VALUES (ROW_COUNT()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (SESSION_USER()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (SLEEP(1)); #marked unsafe in BUG#47995 +INSERT INTO t1 VALUES (SYSDATE()); #marked unsafe in BUG#47995 +INSERT INTO t1 VALUES (SYSTEM_USER()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (USER()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (UUID()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (UUID_SHORT()); #marked unsafe before BUG#47995 +INSERT INTO t1 VALUES (VERSION()); #marked unsafe in BUG#47995 +INSERT INTO t1 VALUES (RAND()); #marked unsafe in BUG#49222 +INSERT INTO t1 VALUES (RANDOM_BYTES(1000)); #marked unsafe in MDEV-25704 +DELETE FROM t1; + +# Since we replicate the TIMESTAMP variable, functions affected by the +# TIMESTAMP variable are safe to replicate. So we check that the +# following following functions that depend on the TIMESTAMP variable +# are not unsafe and don't generate a warning. + +SET TIME_ZONE= '+03:00'; +SET TIMESTAMP=1000000; +INSERT INTO t1 VALUES + (CURDATE()), + (CURRENT_DATE()), + (CURRENT_TIME()), + (CURRENT_TIMESTAMP()), + (CURTIME()), + (LOCALTIME()), + (LOCALTIMESTAMP()), + (NOW()), + (UNIX_TIMESTAMP()), + (UTC_DATE()), + (UTC_TIME()), + (UTC_TIMESTAMP()); +SELECT * FROM t1; + +DROP TABLE t1; +# +#BUG#11758262-50439: MARK INSERT...SEL...ON DUP KEY UPD,REPLACE.. +#The following statement may be unsafe when logged in statement format. +#INSERT IGNORE...SELECT +#INSERT ... SELECT ... ON DUPLICATE KEY UPDATE +#REPLACE ... SELECT +#UPDATE IGNORE +#CREATE TABLE... IGNORE SELECT +#CREATE TABLE... REPLACE SELECT +# +###BUG 11765650 - 58637: MARK UPDATES THAT DEPEND ON ORDER OF TWO KEYS UNSAFE +#INSERT.... ON DUP KEY UPDATE on a table with more than one UNIQUE KEY + +#setup tables +CREATE TABLE filler_table (a INT, b INT); +INSERT INTO filler_table values (1,1),(1,2); +CREATE TABLE insert_table (a INT, b INT, PRIMARY KEY(a)); +CREATE TABLE replace_table (a INT, b INT, PRIMARY KEY(a)); +INSERT INTO replace_table values (1,1),(2,2); +CREATE TABLE update_table (a INT, b INT, PRIMARY KEY(a)); +INSERT INTO update_table values (1,1),(2,2); +CREATE TABLE insert_2_keys (a INT UNIQUE KEY, b INT UNIQUE KEY); +INSERT INTO insert_2_keys values (1, 1); + +#INSERT IGNORE... SELECT +INSERT IGNORE INTO insert_table SELECT * FROM filler_table; +TRUNCATE TABLE insert_table; +#INSERT ... SELECT ... ON DUPLICATE KEY UPDATE +INSERT INTO insert_table SELECT * FROM filler_table ON DUPLICATE KEY UPDATE a = 1; +TRUNCATE TABLE insert_table; +#REPLACE...SELECT +REPLACE INTO replace_table SELECT * FROM filler_table; +#UPDATE IGNORE +UPDATE IGNORE update_table SET a=2; +#CREATE TABLE [IGNORE/REPLACE] SELECT +CREATE TABLE create_ignore_test (a INT, b INT, PRIMARY KEY(b)) IGNORE SELECT * FROM filler_table; +CREATE TABLE create_replace_test (a INT, b INT, PRIMARY KEY(b)) REPLACE SELECT * FROM filler_table; +#temporary tables should not throw the warning. +CREATE TEMPORARY TABLE temp1 (a INT, b INT, PRIMARY KEY(b)) REPLACE SELECT * FROM filler_table; + +#INSERT.... ON DUP KEY UPDATE on a table with more than one UNIQUE KEY +INSERT INTO insert_2_keys VALUES (1, 2) + ON DUPLICATE KEY UPDATE a=VALUES(a)+10, b=VALUES(b)+10; + +###clean up +DROP TABLE filler_table; +DROP TABLE insert_table; +DROP TABLE update_table; +DROP TABLE replace_table; +DROP TABLE create_ignore_test; +DROP TABLE create_replace_test; +DROP TABLE insert_2_keys; + +--echo "End of tests" diff --git a/mysql-test/suite/binlog/t/binlog_variables_log_bin-master.opt b/mysql-test/suite/binlog/t/binlog_variables_log_bin-master.opt new file mode 100644 index 00000000..85d14ea7 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_variables_log_bin-master.opt @@ -0,0 +1 @@ +--log-bin=other diff --git a/mysql-test/suite/binlog/t/binlog_variables_log_bin.test b/mysql-test/suite/binlog/t/binlog_variables_log_bin.test new file mode 100644 index 00000000..afaea3d9 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_variables_log_bin.test @@ -0,0 +1,5 @@ +--source include/not_embedded.inc + +let $log_bin_index=`select substring_index(@@log_bin_index,'/',-1)`; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR $log_bin_index mysqld-bin.index +--query_vertical SHOW VARIABLES LIKE 'log_bin%' diff --git a/mysql-test/suite/binlog/t/binlog_variables_log_bin_index-master.opt b/mysql-test/suite/binlog/t/binlog_variables_log_bin_index-master.opt new file mode 100644 index 00000000..68e580bd --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_variables_log_bin_index-master.opt @@ -0,0 +1,2 @@ +--log-bin=other +--log-bin-index=$MYSQLTEST_VARDIR/tmp/something.index diff --git a/mysql-test/suite/binlog/t/binlog_variables_log_bin_index.test b/mysql-test/suite/binlog/t/binlog_variables_log_bin_index.test new file mode 100644 index 00000000..d94d565d --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_variables_log_bin_index.test @@ -0,0 +1,4 @@ +--source include/not_embedded.inc + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--query_vertical SHOW VARIABLES LIKE 'log_bin%' diff --git a/mysql-test/suite/binlog/t/binlog_variables_relay_log-master.opt b/mysql-test/suite/binlog/t/binlog_variables_relay_log-master.opt new file mode 100644 index 00000000..a01432d7 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_variables_relay_log-master.opt @@ -0,0 +1 @@ +--relay-log=other-relay diff --git a/mysql-test/suite/binlog/t/binlog_variables_relay_log.test b/mysql-test/suite/binlog/t/binlog_variables_relay_log.test new file mode 100644 index 00000000..27ef1d73 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_variables_relay_log.test @@ -0,0 +1,5 @@ +--source include/not_embedded.inc + +let $relay_log_index=`select substring_index(@@relay_log_index,'/',-1)`; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR $relay_log_index mysqld-relay-bin.index +--query_vertical SHOW VARIABLES LIKE 'relay_log%' diff --git a/mysql-test/suite/binlog/t/binlog_variables_relay_log_index-master.opt b/mysql-test/suite/binlog/t/binlog_variables_relay_log_index-master.opt new file mode 100644 index 00000000..eeabaca1 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_variables_relay_log_index-master.opt @@ -0,0 +1,2 @@ +--relay-log=other-relay +--relay-log-index=$MYSQLTEST_VARDIR/tmp/something-relay.index diff --git a/mysql-test/suite/binlog/t/binlog_variables_relay_log_index.test b/mysql-test/suite/binlog/t/binlog_variables_relay_log_index.test new file mode 100644 index 00000000..1e987901 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_variables_relay_log_index.test @@ -0,0 +1,4 @@ +--source include/not_embedded.inc + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--query_vertical SHOW VARIABLES LIKE 'relay_log%' diff --git a/mysql-test/suite/binlog/t/binlog_verbose_compressed_fields.test b/mysql-test/suite/binlog/t/binlog_verbose_compressed_fields.test new file mode 100644 index 00000000..8cbcdbef --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_verbose_compressed_fields.test @@ -0,0 +1,70 @@ +# +# Purpose: +# This test validates that mysqlbinlog is able to annotate compressed column +# types with two levels of verbosity. +# +# Methodology: +# Validate that the output from mysqlbinlog -vv after creating and inserting +# into a table with compressed and uncompressed fields correctly annotates +# which columns are compressed +# +# References: +# MDEV-25277: mysqlbinlog --verbose cannot read row events with compressed +# columns: Don't know how to handle column type: 140 +# +--source include/have_binlog_format_row.inc + +CREATE TABLE t1 (a TEXT, ac TEXT COMPRESSED, b TINYTEXT, bc TINYTEXT COMPRESSED, c MEDIUMTEXT, cc MEDIUMTEXT COMPRESSED, d LONGTEXT, dc LONGTEXT COMPRESSED, e VARCHAR(10), ec VARCHAR(10) COMPRESSED); + +--echo # Isolate row event into its own binary log +FLUSH BINARY LOGS; +INSERT INTO t1 VALUES ('mya', 'myac', 'myb', 'mybc', 'myc', 'mycc', 'myd', 'mydc', 'mye', 'myec'); +FLUSH BINARY LOGS; + +--let $binlog_file= query_get_value(SHOW BINARY LOGS, Log_name, 2) +--let $datadir= `SELECT @@datadir` +--let $result_binlog= $MYSQLTEST_VARDIR/tmp/$binlog_file + +--echo # MYSQLBINLOG --base64-output=decode-rows -vv datadir/binlog_file --result-file=result_binlog +--exec $MYSQL_BINLOG --base64-output=decode-rows -vv $datadir/$binlog_file --result-file=$result_binlog + +--let $assert_file= $result_binlog +--let $assert_count= 1 + +--let $assert_text= Ensure compressed TEXT fields are annotated correctly +--let $assert_select=\WTEXT COMPRESSED +--source include/assert_grep.inc + +--let $assert_text= Ensure compressed TINYTEXT fields are annotated correctly +--let $assert_select=\WTINYTEXT COMPRESSED +--source include/assert_grep.inc + +--let $assert_text= Ensure compressed MEDIUMTEXT fields are annotated correctly +--let $assert_select=\WMEDIUMTEXT COMPRESSED +--source include/assert_grep.inc + +--let $assert_text= Ensure compressed LONGTEXT fields are annotated correctly +--let $assert_select=\WLONGTEXT COMPRESSED +--source include/assert_grep.inc + +--let $assert_text= Ensure compressed VARSTRING fields are annotated correctly +--let $assert_select=\WVARSTRING\(\d+\) COMPRESSED +--source include/assert_grep.inc + +--let $assert_text= Ensure COMPRESSED only shows up for corresponding fields +--let $assert_count= 5 +--let $assert_select= COMPRESSED +--source include/assert_grep.inc + +--let $assert_text= Ensure non-compressed TEXT fields are annotated correctly +--let $assert_count= 8 +--let $assert_select=/*.*TEXT +--source include/assert_grep.inc + +--let $assert_text= Ensure non-compressed VARSTRING fields are annotated correctly +--let $assert_count= 2 +--let $assert_select=/*.*VARSTRING +--source include/assert_grep.inc + +# Cleanup +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/binlog_write_error.test b/mysql-test/suite/binlog/t/binlog_write_error.test new file mode 100644 index 00000000..bd1cb530 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_write_error.test @@ -0,0 +1,84 @@ +# +# This file is included by binlog_encryption.binlog_write_error +# Please check all dependent tests after modifying it +# + +# +# === Name === +# +# binlog_write_error.test +# +# === Description === +# +# This test case check if the error of writing binlog file is properly +# reported and handled when executing statements. +# +# === Related Bugs === +# +# BUG#37148 +# + +source include/have_debug.inc; +source include/have_binlog_format_mixed_or_statement.inc; + +call mtr.add_suppression("Write to binary log failed: Error writing file*"); + +--echo # +--echo # Test injecting binlog write error when executing queries +--echo # + +let $query= CREATE TABLE t1 (a INT); +source include/binlog_inject_error.inc; + +INSERT INTO t1 VALUES (1),(2),(3); + +let $query= INSERT INTO t1 VALUES (4),(5),(6); +source include/binlog_inject_error.inc; + +let $query= UPDATE t1 set a=a+1; +source include/binlog_inject_error.inc; + +let $query= DELETE FROM t1; +source include/binlog_inject_error.inc; + +let $query= CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t1 VALUES (new.a + 100); +source include/binlog_inject_error.inc; + +let $query= DROP TRIGGER tr1; +source include/binlog_inject_error.inc; + +let $query= ALTER TABLE t1 ADD (b INT); +source include/binlog_inject_error.inc; + +let $query= CREATE VIEW v1 AS SELECT a FROM t1; +source include/binlog_inject_error.inc; + +let $query= DROP VIEW v1; +source include/binlog_inject_error.inc; + +let $query= CREATE PROCEDURE p1(OUT rows_cnt INT) SELECT count(*) INTO rows_cnt FROM t1; +source include/binlog_inject_error.inc; + +let $query= DROP PROCEDURE p1; +source include/binlog_inject_error.inc; + +let $query= DROP TABLE t1; +source include/binlog_inject_error.inc; + +let $query= CREATE FUNCTION f1() RETURNS INT return 1; +source include/binlog_inject_error.inc; + +let $query= DROP FUNCTION f1; +source include/binlog_inject_error.inc; + +let $query= CREATE USER user1; +source include/binlog_inject_error.inc; + +let $query= REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1; +source include/binlog_inject_error.inc; + +let $query= SET PASSWORD FOR user1=PASSWORD('foobar'); +source include/binlog_inject_error.inc; + +let $query= DROP USER user1; +source include/binlog_inject_error.inc; diff --git a/mysql-test/suite/binlog/t/binlog_xa_checkpoint.test b/mysql-test/suite/binlog/t/binlog_xa_checkpoint.test new file mode 100644 index 00000000..b208d02c --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_xa_checkpoint.test @@ -0,0 +1,57 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/have_binlog_format_row.inc + +RESET MASTER; + +CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb; + +# Test that +# 1. XA PREPARE is binlogged before the XA has been prepared in Engine +# 2. While XA PREPARE already binlogged in an old binlog file which has been rotated, +# Binlog checkpoint is not generated for the latest log until +# XA PREPARE returns, e.g OK to the client. + + +# con1 will hang before doing commit checkpoint, blocking RESET MASTER. +connect(con1,localhost,root,,); +SET DEBUG_SYNC= "at_unlog_xa_prepare SIGNAL con1_ready WAIT_FOR con1_go"; +XA START '1'; +INSERT INTO t1 SET a=1; +XA END '1'; +--send XA PREPARE '1'; + + +connection default; +SET DEBUG_SYNC= "now WAIT_FOR con1_ready"; +FLUSH LOGS; +FLUSH LOGS; +FLUSH LOGS; + +--source include/show_binary_logs.inc +--let $binlog_file= master-bin.000004 +--let $binlog_start= 4 +--source include/show_binlog_events.inc + +SET DEBUG_SYNC= "now SIGNAL con1_go"; + +connection con1; +reap; +--echo *** master-bin.000004 checkpoint must show up now *** +--source include/wait_for_binlog_checkpoint.inc + +# Todo: think about the error code returned, move to an appropriate test, or remove +# connection default; +#--error 1399 +# DROP TABLE t1; + +connection con1; +XA ROLLBACK '1'; +SET debug_sync = 'reset'; + +# Clean up. +connection default; + +DROP TABLE t1; +SET debug_sync = 'reset'; diff --git a/mysql-test/suite/binlog/t/binlog_xa_handling.test b/mysql-test/suite/binlog/t/binlog_xa_handling.test new file mode 100644 index 00000000..c454e831 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_xa_handling.test @@ -0,0 +1,28 @@ +############################################################################### +# Bug#19928622: ASSERTION `! IS_SET()' FAILED. | ABORT IN +# DIAGNOSTICS_AREA::SET_OK_STATUS +# +# MDEV-27536 Invalid BINLOG_BASE64_EVENT and assertion Diagnostics_area:: !is_set() +# +# Test: +# ===== +# Begin an XA transaction and execte a DML statement so that XA state becomes +# XA_ACTIVE. Execute the BINLOG command it should not cause any assert. +# Execution should be successful. +############################################################################### +--source include/have_log_bin.inc +--source include/have_innodb.inc + +--connection default +CREATE TABLE t1(f1 int) ENGINE=Innodb; + +XA START 'xa'; +INSERT INTO t1 VALUES(10); +BINLOG ' +SOgWTg8BAAAAbgAAAHIAAAAAAAQANS42LjMtbTUtZGVidWctbG9nAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAABI6BZOEzgNAAgAEgAEBAQEEgAAVgAEGggAAAAICAgCAAAAAAVAYI8='; +XA END 'xa'; +XA PREPARE 'xa'; +XA ROLLBACK 'xa'; + +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/binlog_xa_prepared.inc b/mysql-test/suite/binlog/t/binlog_xa_prepared.inc new file mode 100644 index 00000000..e93832db --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_xa_prepared.inc @@ -0,0 +1,106 @@ +--source include/have_innodb.inc +--source include/have_perfschema.inc +# +# The test verifies binlogging of XA transaction and state of prepared XA +# as far as binlog is concerned. +# +# The prepared XA transactions can be disconnected from the client, +# discovered from another connection and commited or rolled back +# later. They also survive the server restart. The test runs two +# loops each consisting of prepared XA:s generation, their +# manipulation and a server restart followed with survived XA:s +# completion. +# +# Prepared XA can't get available to an external connection +# until connection that either leaves actively or is killed +# has completed a necessary part of its cleanup. +# Selecting from P_S.threads provides a method to learn that. +# +# Total number of connection each performing one insert into table +--let $conn_number=20 +# Number of rollbacks and commits from either side of the server restart +--let $rollback_number=5 +--let $commit_number=5 +# Number of transactions that are terminated before server restarts +--let $term_number=`SELECT $rollback_number + $commit_number` +# Instead of disconnect make some connections killed when their +# transactions got prepared. +--let $killed_number=5 +# make some connections disconnected by shutdown rather than actively +--let $server_disconn_number=5 +--let $prepared_at_server_restart = `SELECT $conn_number - $term_number` +# number a "warmup" connection after server restart, they all commit +--let $post_restart_conn_number=10 + +# Counter to be used in GTID consistency check. +# It's incremented per each non-XA transaction commit. +# Local to this file variable to control one-phase commit loop +--let $one_phase_number = 5 + +--connection default + +# Remove possibly preceeding binlogs and clear initialization time +# GTID executed info. In the following all transactions are counted +# to conduct verification at the end of the test. +if (`SELECT @@global.log_bin`) +{ + RESET MASTER; +} + +# Disconected and follower threads need synchronization +CREATE VIEW v_processlist as SELECT * FROM performance_schema.threads where type = 'FOREGROUND'; + +--eval call mtr.add_suppression("Found $prepared_at_server_restart prepared XA transactions") + +CREATE TABLE t (a INT) ENGINE=innodb; + +# MDEV-515 takes X-lock on the table for the first insert. +# So concurrent insert won't happen on the table +INSERT INTO t VALUES(100); + +# Counter is incremented at the end of post restart to +# reflect number of loops done in correctness computation. +--let $restart_number = 0 +--let $how_to_restart=restart_mysqld.inc +--source suite/binlog/include/binlog_xa_prepared_do_and_restart.inc + +--let $how_to_restart=kill_and_restart_mysqld.inc +--source suite/binlog/include/binlog_xa_prepared_do_and_restart.inc + +--connection default + +# Few xs that commit in one phase, not subject to the server restart +# nor reconnect. +# This piece of test is related to mysqlbinlog recovery examine below. +--let $k = 0 +while ($k < $one_phase_number) +{ + --eval XA START 'one_phase_trx_$k' + --eval INSERT INTO t SET a=$k + --eval XA END 'one_phase_trx_$k' + --eval XA COMMIT 'one_phase_trx_$k' ONE PHASE + + --inc $k +} + +SELECT SUM(a) FROM t; +DROP TABLE t; +DROP VIEW v_processlist; + +let $outfile= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql; +if (`SELECT @@global.log_bin`) +{ + # Recording proper samples of binlogged prepared XA:s + --source include/show_binlog_events.inc + --exec $MYSQL_BINLOG -R --to-last-log master-bin.000001 > $outfile +} + +--echo All transactions must be completed, to empty-list the following: +XA RECOVER; + +if (`SELECT @@global.log_bin`) +{ + --exec $MYSQL test < $outfile + --remove_file $outfile + XA RECOVER; +} diff --git a/mysql-test/suite/binlog/t/binlog_xa_prepared_disconnect.test b/mysql-test/suite/binlog/t/binlog_xa_prepared_disconnect.test new file mode 100644 index 00000000..2a318403 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_xa_prepared_disconnect.test @@ -0,0 +1,11 @@ +############################################################################### +# Bug#12161 Xa recovery and client disconnection +# Testing new server options and binary logging prepared XA transaction. +############################################################################### + +# +# MIXED mode is chosen because formats are varied inside the sourced tests. +# +--source include/have_binlog_format_mixed.inc + +--source suite/binlog/t/binlog_xa_prepared.inc diff --git a/mysql-test/suite/binlog/t/binlog_xa_recover.opt b/mysql-test/suite/binlog/t/binlog_xa_recover.opt new file mode 100644 index 00000000..f645a058 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_xa_recover.opt @@ -0,0 +1 @@ +--loose-skip-stack-trace --skip-core-file --loose-debug-dbug=+d,xa_recover_expect_master_bin_000004 diff --git a/mysql-test/suite/binlog/t/binlog_xa_recover.test b/mysql-test/suite/binlog/t/binlog_xa_recover.test new file mode 100644 index 00000000..3b2a7e45 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_xa_recover.test @@ -0,0 +1,277 @@ +# +# This include file is used by more than one test suite +# (currently binlog and binlog_encryption). +# Please check all dependent tests after modifying it +# + +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/have_binlog_format_row.inc +--source include/have_perfschema.inc +# Valgrind does not work well with test that crashes the server +--source include/not_valgrind.inc + +# (We do not need to restore these settings, as we crash the server). +SET GLOBAL max_binlog_size= 4096; +SET GLOBAL innodb_flush_log_at_trx_commit= 1; +RESET MASTER; + +CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb; +# Insert some data to force a couple binlog rotations (3), so we get some +# normal binlog checkpoints before starting the test. +INSERT INTO t1 VALUES (100, REPEAT("x", 4100)); +# Wait for the master-bin.000002 binlog checkpoint to appear. +--let $wait_for_all= 0 +--let $show_statement= SHOW BINLOG EVENTS IN "master-bin.000002" +--let $field= Info +--let $condition= = "master-bin.000002" +--source include/wait_show_condition.inc +INSERT INTO t1 VALUES (101, REPEAT("x", 4100)); +--let $wait_for_all= 0 +--let $show_statement= SHOW BINLOG EVENTS IN "master-bin.000003" +--let $field= Info +--let $condition= = "master-bin.000003" +--source include/wait_show_condition.inc +INSERT INTO t1 VALUES (102, REPEAT("x", 4100)); +--let $wait_for_all= 0 +--let $show_statement= SHOW BINLOG EVENTS IN "master-bin.000004" +--let $field= Info +--let $condition= = "master-bin.000004" +--source include/wait_show_condition.inc + +# Now start a bunch of transactions that span multiple binlog +# files. Leave then in the state prepared-but-not-committed in the engine +# and crash the server. Check that crash recovery is able to recover all +# of them. +# +# We use debug_sync to get all the transactions into the prepared state before +# we commit any of them. This is because the prepare step flushes the InnoDB +# redo log - including any commits made before, so recovery would become +# unnecessary, decreasing the value of this test. +# +# We arrange to have con1 with a prepared transaction in master-bin.000004, +# con2 and con3 with a prepared transaction in master-bin.000005, and a new +# empty master-bin.000006. So the latest binlog checkpoint should be +# master-bin.000006. + +connect(con1,localhost,root,,); +# First wait after prepare and before write to binlog. +SET DEBUG_SYNC= "ha_commit_trans_before_log_and_order SIGNAL con1_wait WAIT_FOR con1_cont"; +# Then complete InnoDB commit in memory (but not commit checkpoint / write to +# disk), and hang until crash, leaving a transaction to be XA recovered. +SET DEBUG_SYNC= "commit_after_group_release_commit_ordered SIGNAL con1_ready WAIT_FOR _ever"; +send INSERT INTO t1 VALUES (1, REPEAT("x", 4100)); + +connection default; +SET DEBUG_SYNC= "now WAIT_FOR con1_wait"; + +connect(con2,localhost,root,,); +SET DEBUG_SYNC= "ha_commit_trans_before_log_and_order SIGNAL con2_wait WAIT_FOR con2_cont"; +SET DEBUG_SYNC= "commit_after_group_release_commit_ordered SIGNAL con2_ready WAIT_FOR _ever"; +send INSERT INTO t1 VALUES (2, NULL); + +connection default; +SET DEBUG_SYNC= "now WAIT_FOR con2_wait"; + +connect(con3,localhost,root,,); +SET DEBUG_SYNC= "ha_commit_trans_before_log_and_order SIGNAL con3_wait WAIT_FOR con3_cont"; +SET DEBUG_SYNC= "commit_after_group_release_commit_ordered SIGNAL con3_ready WAIT_FOR _ever"; +send INSERT INTO t1 VALUES (3, REPEAT("x", 4100)); + +connection default; +SET DEBUG_SYNC= "now WAIT_FOR con3_wait"; + +connect(con4,localhost,root,,); +SET DEBUG_SYNC= "ha_commit_trans_before_log_and_order SIGNAL con4_wait WAIT_FOR con4_cont"; +SET SESSION debug_dbug="+d,crash_commit_after_log"; +send INSERT INTO t1 VALUES (4, NULL); + +connection default; +SET DEBUG_SYNC= "now WAIT_FOR con4_wait"; + +SET DEBUG_SYNC= "now SIGNAL con1_cont"; +SET DEBUG_SYNC= "now WAIT_FOR con1_ready"; +SET DEBUG_SYNC= "now SIGNAL con2_cont"; +SET DEBUG_SYNC= "now WAIT_FOR con2_ready"; +SET DEBUG_SYNC= "now SIGNAL con3_cont"; +SET DEBUG_SYNC= "now WAIT_FOR con3_ready"; + +# Check that everything is committed in binary log. +--source include/show_binary_logs.inc +--let $binlog_file= master-bin.000003 +--let $binlog_start= 4 +--source include/show_binlog_events.inc +--let $binlog_file= master-bin.000004 +--source include/show_binlog_events.inc +--let $binlog_file= master-bin.000005 +--source include/show_binlog_events.inc +--let $binlog_file= master-bin.000006 +--source include/show_binlog_events.inc + + +# Check that server will not purge too much. +PURGE BINARY LOGS TO "master-bin.000006"; +--source include/show_binary_logs.inc + +# Now crash the server with one more transaction in prepared state. +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait-binlog_xa_recover.test +EOF +--error 0,2006,2013 +SET DEBUG_SYNC= "now SIGNAL con4_cont"; +connection con4; +--error 2006,2013 +reap; + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart-group_commit_binlog_pos.test +EOF + +connection default; +--enable_reconnect +--source include/wait_until_connected_again.inc + +# Check that all transactions are recovered. +SELECT a FROM t1 ORDER BY a; + +--echo Test that with multiple binlog checkpoints, recovery starts from the last one. +SET GLOBAL max_binlog_size= 4096; +SET GLOBAL innodb_flush_log_at_trx_commit= 1; +RESET MASTER; + +# Rotate to binlog master-bin.000003 while delaying binlog checkpoints. +# So we get multiple binlog checkpoints in master-bin.000003. +# Then complete the checkpoints, crash, and check that we only scan +# the necessary binlog file (ie. that we use the _last_ checkpoint). + +connect(con10,localhost,root,,); +SET DEBUG_SYNC= "commit_after_group_release_commit_ordered SIGNAL con10_ready WAIT_FOR con10_cont"; +send INSERT INTO t1 VALUES (10, REPEAT("x", 4100)); + +connection default; +SET DEBUG_SYNC= "now WAIT_FOR con10_ready"; + +connect(con11,localhost,root,,); +SET DEBUG_SYNC= "commit_after_group_release_commit_ordered SIGNAL con11_ready WAIT_FOR con11_cont"; +send INSERT INTO t1 VALUES (11, REPEAT("x", 4100)); + +connection default; +SET DEBUG_SYNC= "now WAIT_FOR con11_ready"; + +connect(con12,localhost,root,,); +SET DEBUG_SYNC= "commit_after_group_release_commit_ordered SIGNAL con12_ready WAIT_FOR con12_cont"; +send INSERT INTO t1 VALUES (12, REPEAT("x", 4100)); + +connection default; +SET DEBUG_SYNC= "now WAIT_FOR con12_ready"; +INSERT INTO t1 VALUES (13, NULL); + +--source include/show_binary_logs.inc +--let $binlog_file= master-bin.000004 +--let $binlog_start= 4 +--source include/show_binlog_events.inc + +SET DEBUG_SYNC= "now SIGNAL con10_cont"; +connection con10; +reap; +connection default; + +# We need to sync the test case with the background processing of the +# commit checkpoint, otherwise we get nondeterministic results. +let $wait_condition= select count(*) = 1 from performance_schema.threads where processlist_state = "Waiting for background binlog tasks"; +--source include/wait_condition.inc + +SET DEBUG_SYNC= "now SIGNAL con12_cont"; +connection con12; +reap; +connection default; + +SET DEBUG_SYNC= "now SIGNAL con11_cont"; +connection con11; +reap; + +connection default; +# Wait for the last (master-bin.000004) binlog checkpoint to appear. +--let $wait_for_all= 0 +--let $show_statement= SHOW BINLOG EVENTS IN "master-bin.000004" +--let $field= Info +--let $condition= = "master-bin.000004" +--source include/wait_show_condition.inc + +--echo Now crash the server +# It is not too easy to test XA recovery, as it runs early during server +# startup, before any connections can be made. +# What we do is set a DBUG error insert which will crash if XA recovery +# starts from any other binlog than master-bin.000004 (check the file +# binlog_xa_recover-master.opt). Then we will fail here if XA recovery +# would start from the wrong place. +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait-binlog_xa_recover.test +EOF +SET SESSION debug_dbug="+d,crash_commit_after_log"; +--error 2006,2013 +INSERT INTO t1 VALUES (14, NULL); + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart-group_commit_binlog_pos.test +EOF + +connection default; +--enable_reconnect +--source include/wait_until_connected_again.inc + +# Check that all transactions are recovered. +SELECT a FROM t1 ORDER BY a; + + +--echo *** Check that recovery works if we crashed early during rotate, before +--echo *** binlog checkpoint event could be written. + +SET GLOBAL max_binlog_size= 4096; +SET GLOBAL innodb_flush_log_at_trx_commit= 1; +RESET MASTER; + +# We need some initial data to reach binlog master-bin.000004. Otherwise +# crash recovery fails due to the error insert used for previous test. +INSERT INTO t1 VALUES (21, REPEAT("x", 4100)); +INSERT INTO t1 VALUES (22, REPEAT("x", 4100)); +# Wait for the master-bin.000003 binlog checkpoint to appear. +--let $wait_for_all= 0 +--let $show_statement= SHOW BINLOG EVENTS IN "master-bin.000003" +--let $field= Info +--let $condition= = "master-bin.000003" +--source include/wait_show_condition.inc +INSERT INTO t1 VALUES (23, REPEAT("x", 4100)); +# Wait for the last (master-bin.000004) binlog checkpoint to appear. +--let $wait_for_all= 0 +--let $show_statement= SHOW BINLOG EVENTS IN "master-bin.000004" +--let $field= Info +--let $condition= = "master-bin.000004" +--source include/wait_show_condition.inc + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait-binlog_xa_recover.test +EOF +SET SESSION debug_dbug="+d,crash_before_write_checkpoint_event"; +--error 2006,2013 +INSERT INTO t1 VALUES (24, REPEAT("x", 4100)); + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart-group_commit_binlog_pos.test +EOF + +--enable_reconnect +--source include/wait_until_connected_again.inc + +# Check that all transactions are recovered. +SELECT a FROM t1 ORDER BY a; + +--source include/show_binary_logs.inc +--let $binlog_file= master-bin.000004 +--let $binlog_start= 4 +--source include/show_binlog_events.inc + +# Cleanup +connection default; +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/binlog_xa_recover_using_new_server_id.test b/mysql-test/suite/binlog/t/binlog_xa_recover_using_new_server_id.test new file mode 100644 index 00000000..a7f2a206 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_xa_recover_using_new_server_id.test @@ -0,0 +1,44 @@ +# This test verifies attempt to xa recover using a new server id that +# different from the transaction's original server_id. +# + +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_binlog_format_row.inc +# Valgrind does not work well with test that crashes the server +--source include/not_valgrind.inc + + +--echo ========= Set server_id to 99 and prepare test table. +SET GLOBAL server_id= 99; +CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb; + + +--echo ========= Crash the server. +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait-binlog_xa_recover_using_new_server_id.test +EOF +SET SESSION debug_dbug="+d,crash_commit_after_log"; +--error 2006,2013 +INSERT INTO t1 VALUES (1, NULL); + + +--echo ========= Restart the server with default config file in which server_id= 1. +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart-binlog_xa_recover_using_new_server_id.test +EOF + + +--echo ========= Check that recover succeeds and server is up. +connection default; +--enable_reconnect +--source include/wait_until_connected_again.inc + + +--echo ========= Check that all transactions are recovered. +SELECT a FROM t1 ORDER BY a; + + +--echo ========= Cleanup. +connection default; +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/flashback-largebinlog.test b/mysql-test/suite/binlog/t/flashback-largebinlog.test new file mode 100644 index 00000000..80b0da52 --- /dev/null +++ b/mysql-test/suite/binlog/t/flashback-largebinlog.test @@ -0,0 +1,114 @@ +# mysqlbinlog_big.test +# +# Show that mysqlbinlog can handle big rows. +# + +# +# The *huge* output of mysqlbinlog will be redirected to +# $MYSQLTEST_VARDIR/$mysqlbinlog_output +# +--let $mysqlbinlog_output= tmp/mysqlbinlog_big_1.out + +--source include/have_binlog_format_row.inc +--source include/have_log_bin.inc + +# This is a big test. +--source include/big_test.inc +--source include/not_msan.inc +# Test needs more than 4G of memory +--source include/have_64bit.inc + +--echo # +--echo # Preparatory cleanup. +--echo # +--disable_warnings +drop database if exists mysqltest; +create database mysqltest; +use mysqltest; +DROP TABLE IF EXISTS t1; +--enable_warnings + +--echo # +--echo # We need a fixed timestamp to avoid varying results. +--echo # +SET timestamp=1000000000; + +--echo # +--echo # We need big packets. +--echo # +--echo # Capture initial value to reset at the end of the test +# use let $<var> = query_get_value as FLUSH statements +# in the test will set @<var> values to NULL +let $orig_max_allowed_packet = +query_get_value(SELECT @@global.max_allowed_packet, @@global.max_allowed_packet, 1); + +--echo # Now adjust max_allowed_packet +SET @@global.max_allowed_packet= 10*1024*1024*1024; + +--echo max_allowed_packet is a global variable. +--echo In order for the preceding change in max_allowed_packets' value +--echo to be seen and used, we must start a new connection. +--echo The change does not take effect with the current one. +--echo For simplicity, we just disconnect / reconnect connection default here. +disconnect default; +connect (default, localhost,root,,); + +--echo # +--echo # Delete all existing binary logs. +--echo # +RESET MASTER; + +--echo # +--echo # Create a test table. +--echo # +use mysqltest; +eval CREATE TABLE t1 ( + c1 LONGTEXT + ) DEFAULT CHARSET latin1; + +--echo # +--echo # Show how many rows are affected by each statement. +--echo # +--enable_info + +--echo # +--echo # Insert some big rows. +--echo # + +--echo insert 1024MB data twice +INSERT INTO t1 VALUES (REPEAT('ManyMegaByteBlck', 67108864)); +INSERT INTO t1 VALUES (REPEAT('MegaByteBlckMany', 67108864)); + +--echo # +--echo # Flush all log buffers to the log file. +--echo # +FLUSH LOGS; + +--echo # +--echo # Call mysqlbinlog to display the log file contents. +--echo # NOTE: The output of mysqlbinlog is redirected to +--echo # \$MYSQLTEST_VARDIR/$mysqlbinlog_output +--echo # If you want to examine it, disable remove_file +--echo # at the bottom of the test script. +--echo # +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_result $MYSQLTEST_VARDIR <MYSQLTEST_VARDIR> +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /Xid = [0-9]*/Xid = #/ +--exec $MYSQL_BINLOG -B -v -v $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/$mysqlbinlog_output + +--echo # +--echo # Cleanup. +--echo # +--echo # reset variable value to pass testcase checks +--disable_query_log +eval SET @@global.max_allowed_packet = $orig_max_allowed_packet; +--enable_query_log +DROP TABLE t1; +drop database if exists mysqltest; + +--echo remove_file \$MYSQLTEST_VARDIR/$mysqlbinlog_output +# +# NOTE: If you want to see the *huge* mysqlbinlog output, disable next line: +# +--remove_file $MYSQLTEST_VARDIR/$mysqlbinlog_output + diff --git a/mysql-test/suite/binlog/t/flashback-master.opt b/mysql-test/suite/binlog/t/flashback-master.opt new file mode 100644 index 00000000..476efbe2 --- /dev/null +++ b/mysql-test/suite/binlog/t/flashback-master.opt @@ -0,0 +1,2 @@ +--flashback +--timezone=GMT-8 diff --git a/mysql-test/suite/binlog/t/flashback.test b/mysql-test/suite/binlog/t/flashback.test new file mode 100644 index 00000000..7c58b56c --- /dev/null +++ b/mysql-test/suite/binlog/t/flashback.test @@ -0,0 +1,378 @@ +--source include/have_log_bin.inc +--source include/have_innodb.inc + +--echo # +--echo # Preparatory cleanup. +--echo # +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +--echo # +--echo # We need a fixed timestamp to avoid varying results. +--echo # +SET timestamp=1000000000; + +--echo # < CASE 1 > +--echo # Delete all existing binary logs. +--echo # +RESET MASTER; + +CREATE TABLE t1 ( + c01 tinyint, + c02 smallint, + c03 mediumint, + c04 int, + c05 bigint, + c06 char(10), + c07 varchar(20), + c08 TEXT +) ENGINE=InnoDB; + +--echo # < CASE 1 > +--echo # Insert data to t1 +--echo # +INSERT INTO t1 VALUES(0,0,0,0,0,'','',''); +INSERT INTO t1 VALUES(1,2,3,4,5, "abc", "abcdefg", "abcedfghijklmnopqrstuvwxyz"); +INSERT INTO t1 VALUES(127, 32767, 8388607, 2147483647, 9223372036854775807, repeat('a', 10), repeat('a', 20), repeat('a', 255)); + + +--echo # < CASE 1 > +--echo # Update t1 +--echo # +UPDATE t1 SET c01=100 WHERE c02=0 OR c03=3; + +--echo # < CASE 1 > +--echo # Clear t1 +--echo # +DELETE FROM t1; + +FLUSH LOGS; + +--echo # < CASE 1 > +--echo # Show mysqlbinlog result without -B +--echo # + +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /Xid = [0-9]*/Xid = #/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /server v [^ ]*/server v #.##.##/ /CRC32 0x[0-9a-f]*/CRC32 XXX/ /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ /xid=\d*/xid=<xid>/ +--exec $MYSQL_BINLOG --base64-output=decode-rows -v -v $MYSQLD_DATADIR/master-bin.000001 + +--echo # < CASE 1 > +--echo # Show mysqlbinlog result with -B +--echo # + +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /Xid = [0-9]*/Xid = #/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /server v [^ ]*/server v #.##.##/ /CRC32 0x[0-9a-f]*/CRC32 XXX/ /collation_server=[0-9]+/collation_server=X/ /character_set_client=[a-zA-Z0-9]+/character_set_client=X/ /collation_connection=[0-9]+/collation_connection=X/ /xid=\d*/xid=<xid>/ +--exec $MYSQL_BINLOG -B --base64-output=decode-rows -v -v $MYSQLD_DATADIR/master-bin.000001 + +--echo # < CASE 1 > +--echo # Insert data to t1 +--echo # +TRUNCATE TABLE t1; +INSERT INTO t1 VALUES(0,0,0,0,0,'','',''); +INSERT INTO t1 VALUES(1,2,3,4,5, "abc", "abcdefg", "abcedfghijklmnopqrstuvwxyz"); +INSERT INTO t1 VALUES(127, 32767, 8388607, 2147483647, 9223372036854775807, repeat('a', 10), repeat('a', 20), repeat('a', 60)); + +--echo # < CASE 1 > +--echo # Delete all existing binary logs. +--echo # +RESET MASTER; +SELECT * FROM t1; + +--echo # < CASE 1 > +--echo # Operate some data +--echo # + +UPDATE t1 SET c01=20; +UPDATE t1 SET c02=200; +UPDATE t1 SET c03=2000; + +DELETE FROM t1; + +FLUSH LOGS; + +--echo # < CASE 1 > +--echo # Flashback & Check the result +--echo # + +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_BINLOG -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_1.sql +--exec $MYSQL_BINLOG -B -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_1.sql +--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_1.sql;" + +SELECT * FROM t1; + +RESET MASTER; + +--echo # < CASE 2 > +--echo # UPDATE multi-rows in one event +--echo # + +BEGIN; +UPDATE t1 SET c01=10 WHERE c01=0; +UPDATE t1 SET c01=20 WHERE c01=10; +COMMIT; + +FLUSH LOGS; + +--echo # < CASE 2 > +--echo # Flashback & Check the result +--echo # + +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_BINLOG -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_2.sql +--exec $MYSQL_BINLOG -B -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_2.sql +--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_2.sql;" + +SELECT * FROM t1; + +DROP TABLE t1; + +--echo # < CASE 3 > +--echo # Self-referencing foreign keys +--echo # + +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, FOREIGN KEY my_fk(b) REFERENCES t1(a)) ENGINE=InnoDB; + +BEGIN; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (2, 1), (3, 2), (4, 3); +COMMIT; + +SELECT * FROM t1; + +# New binlog +RESET MASTER; + +DELETE FROM t1 ORDER BY a DESC; + +FLUSH LOGS; + +--echo # < CASE 3 > +--echo # Flashback & Check the result +--echo # + +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_BINLOG -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_3.sql +--exec $MYSQL_BINLOG -B -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_3.sql +--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_3.sql;" + +SELECT * FROM t1; + +DROP TABLE t1; + +--echo # < CASE 4 > +--echo # Trigger +--echo # + +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; + +BEGIN; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (2, 1), (3, 2), (4, 3); +INSERT INTO t2 VALUES (6, 7), (7, 8), (8, 9); +COMMIT; + +SELECT * FROM t1; +SELECT * FROM t2; + +CREATE TRIGGER trg1 BEFORE INSERT ON t1 FOR EACH ROW DELETE FROM t2 WHERE a = NEW.b; + +# New binlog +RESET MASTER; + +INSERT INTO t1 VALUES (5, 6), (7, 8); + +SELECT * FROM t1; +SELECT * FROM t2; + +FLUSH LOGS; + +--echo # < CASE 4 > +--echo # Flashback & Check the result +--echo # + +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_BINLOG -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_4.sql +--exec $MYSQL_BINLOG -B $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_4.sql +--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_4.sql;" + +SELECT * FROM t1; +SELECT * FROM t2; + +DROP TRIGGER trg1; +DROP TABLE t1; +DROP TABLE t2; + +--echo # < CASE 5 > +--echo # REPLCAE Queries +--echo # + +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, UNIQUE uk(b)) ENGINE=InnoDB; + +BEGIN; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (2, 1), (3, 2), (4, 3); +INSERT INTO t1 VALUES (5, 4), (6, 5), (7, 6); +COMMIT; + +SELECT * FROM t1; + +# New binlog +RESET MASTER; + +REPLACE INTO t1 VALUES (3, 100); +REPLACE INTO t1 SET a=4, b=200; + +SELECT * FROM t1; + +REPLACE INTO t1 VALUES (5,5); + +SELECT * FROM t1; + +FLUSH LOGS; + +--echo # < CASE 5 > +--echo # Flashback & Check the result +--echo # + +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_BINLOG -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_5.sql +--exec $MYSQL_BINLOG -B $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_5.sql +--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_5.sql;" + +SELECT * FROM t1; + +DROP TABLE t1; + + +--echo # < CASE 6 > +--echo # Test Case from MDEV-21067 +--echo # + +# Init Structure +CREATE DATABASE world; +CREATE TABLE world.city ( + ID INT AUTO_INCREMENT PRIMARY KEY, + Name VARCHAR(64), + CountryCode VARCHAR(64), + District VARCHAR(64), + Population INT +) ENGINE=InnoDB; +CREATE TABLE test.test ( + ID INT AUTO_INCREMENT PRIMARY KEY, + REC VARCHAR(64), + ts TIMESTAMP +) ENGINE=InnoDB; + +INSERT INTO world.city VALUES (NULL, 'Davenport', 'USA', 'Iowa', 100); +INSERT INTO world.city VALUES (NULL, 'Boulder', 'USA', 'Colorado', 1000); +INSERT INTO world.city VALUES (NULL, 'Gweru', 'ZWE', 'Midlands', 10000); + +RESET MASTER; + +CHECKSUM TABLE world.city; + +# Insert test data +INSERT INTO test.test VALUES (NULL, 'Good record 1', CURRENT_TIMESTAMP()); + +INSERT INTO world.city VALUES (NULL, 'Wrong value 1', '000', 'Wrong', 0); +INSERT INTO world.city VALUES (NULL, 'Wrong value 2', '000', 'Wrong', 0) , (NULL, 'Wrong value 3', '000', 'Wrong', 0); + +INSERT INTO test.test VALUES (NULL, 'Good record 2', CURRENT_TIMESTAMP()); + +UPDATE world.city SET Population = 99999999 WHERE ID IN (1, 2, 3); + +INSERT INTO test.test VALUES (NULL, 'Good record 3', CURRENT_TIMESTAMP()); + +DELETE FROM world.city WHERE ID BETWEEN 1 AND 2; + +INSERT INTO test.test VALUES (NULL, 'Good record 5', CURRENT_TIMESTAMP()); + +REPLACE INTO world.city VALUES (4074, 'Wrong value 4', '000', 'Wrong', 0); +REPLACE INTO world.city VALUES (4078, 'Wrong value 5', '000', 'Wrong', 0), (NULL, 'Wrong value 6', '000', 'Wrong', 0); + +INSERT INTO test.test VALUES (NULL, 'Good record 6', CURRENT_TIMESTAMP()); + +INSERT INTO world.city +SELECT NULL, Name, CountryCode, District, Population FROM world.city WHERE ID BETWEEN 2 AND 10; + +INSERT INTO test.test VALUES (NULL, 'Good record 7', CURRENT_TIMESTAMP()); + +INSERT INTO test.test VALUES (NULL, 'Good record 8', CURRENT_TIMESTAMP()); + +DELETE FROM world.city; + +INSERT INTO test.test VALUES (NULL, 'Good record 9', CURRENT_TIMESTAMP()); + +FLUSH LOGS; + +--echo # < CASE 6 > +--echo # Flashback & Check the result +--echo # + +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_BINLOG --database=world --table=city -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_6.sql +--exec $MYSQL_BINLOG --database=world --table=city -B $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_6.sql +--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_6.sql;" + +SELECT * FROM world.city; + +SELECT * FROM test.test; + +CHECKSUM TABLE world.city; + +DROP TABLE test.test; +DROP TABLE world.city; +DROP DATABASE world; + +--echo # < CASE 7 > +--echo # Test Case for MDEV-17260 +--echo # + +RESET MASTER; + +CREATE TABLE t1 ( f INT PRIMARY KEY ) ENGINE=innodb; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6); +--echo # 6- Rows must be present +SELECT COUNT(*) FROM t1; +FLUSH LOGS; +DELETE FROM t1; +FLUSH LOGS; + +--echo # 0- Rows must be present +--let $assert_cond= COUNT(*) = 0 FROM t1 +--let $assert_text= Table t1 should have 0 rows. +--source include/assert.inc + +--exec $MYSQL_BINLOG -vv -B --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002> $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_7.sql +--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_7.sql;" + +--echo # 6- Rows must be present upon restoring from flashback +--let $assert_cond= COUNT(*) = 6 FROM t1 +--let $assert_text= Table t1 should have six rows. +--source include/assert.inc + +DROP TABLE t1; + +--echo # +--echo # MDEV-30698 Cover missing test cases for mariadb-binlog options +--echo # --raw [and] --flashback +--echo # + +--error 1 # --raw mode and --flashback mode are not allowed +--exec $MYSQL_BINLOG -vv -B --raw --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000003> $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_8.sql + +## Clear +SET binlog_format=statement; +--error ER_FLASHBACK_NOT_SUPPORTED +SET GLOBAL binlog_format=statement; diff --git a/mysql-test/suite/binlog/t/foreign_key.test b/mysql-test/suite/binlog/t/foreign_key.test new file mode 100644 index 00000000..87c719e4 --- /dev/null +++ b/mysql-test/suite/binlog/t/foreign_key.test @@ -0,0 +1,22 @@ +--source include/have_innodb.inc +--source include/have_binlog_format_row.inc + +reset master; + +CREATE TABLE t1 ( + id INT, + k INT, + c CHAR(8), + KEY (k), + PRIMARY KEY (id), + FOREIGN KEY (id) REFERENCES t1 (k) +) ENGINE=InnoDB; +LOCK TABLES t1 WRITE; +SET SESSION FOREIGN_KEY_CHECKS= OFF; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1,1,'foo'); +DROP TABLE t1; +SET SESSION FOREIGN_KEY_CHECKS= ON; +SET AUTOCOMMIT=ON; + +source include/show_binlog_events.inc; diff --git a/mysql-test/suite/binlog/t/innodb_autoinc_lock_mode_binlog.opt b/mysql-test/suite/binlog/t/innodb_autoinc_lock_mode_binlog.opt new file mode 100644 index 00000000..824f656c --- /dev/null +++ b/mysql-test/suite/binlog/t/innodb_autoinc_lock_mode_binlog.opt @@ -0,0 +1 @@ +--innodb_autoinc_lock_mode=2 diff --git a/mysql-test/suite/binlog/t/innodb_autoinc_lock_mode_binlog.test b/mysql-test/suite/binlog/t/innodb_autoinc_lock_mode_binlog.test new file mode 100644 index 00000000..283862ec --- /dev/null +++ b/mysql-test/suite/binlog/t/innodb_autoinc_lock_mode_binlog.test @@ -0,0 +1,21 @@ +--source include/have_innodb.inc +--source include/have_binlog_format_mixed.inc +reset master; #clear up binlogs +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); + +select @@innodb_autoinc_lock_mode; +select @@binlog_format; + +create table t1 (a int not null auto_increment,b int, primary key (a)) engine=InnoDB; +insert into t1 values (NULL,1); +--source include/show_binlog_events.inc + +set global binlog_format=STATEMENT; +--connect (con1,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK) +insert into t1 values (NULL,1); +insert into t1 values (NULL,1); +--disconnect con1 +--connection default + +set global binlog_format=MIXED; +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/innodb_rc_insert_before_delete.test b/mysql-test/suite/binlog/t/innodb_rc_insert_before_delete.test new file mode 100644 index 00000000..228d9778 --- /dev/null +++ b/mysql-test/suite/binlog/t/innodb_rc_insert_before_delete.test @@ -0,0 +1,92 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/have_binlog_format_mixed.inc +--source include/count_sessions.inc + +RESET MASTER; + +# MDEV-30010 merely adds is a Read-Committed version MDEV-30225 test +# solely to prove the RC isolation yields ROW binlog format as it is +# supposed to: +# https://mariadb.com/kb/en/unsafe-statements-for-statement-based-replication/#isolation-levels. +# The original MDEV-30225 test is adapted to the RC to create +# a similar safisticated scenario which does not lead to any deadlock though. + +--connect (pause_purge,localhost,root) +START TRANSACTION WITH CONSISTENT SNAPSHOT; + +--connection default +CREATE TABLE t (pk int PRIMARY KEY, sk INT UNIQUE) ENGINE=InnoDB; +INSERT INTO t VALUES (10, 100); + +--connect (con1,localhost,root) +BEGIN; # trx 0 +SELECT * FROM t WHERE sk = 100 FOR UPDATE; + +--connect (con2,localhost,root) +SET DEBUG_SYNC="lock_wait_start SIGNAL insert_wait_started"; +# trx 1 is locked on try to read the record in secondary index during duplicates +# check. It's the first in waiting queue, that's why it will be woken up firstly +# when trx 0 commits. +--send INSERT INTO t VALUES (5, 100) # trx 1 + +--connect (con3,localhost,root) +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +SET DEBUG_SYNC="now WAIT_FOR insert_wait_started"; +SET DEBUG_SYNC="lock_wait_start SIGNAL delete_started_waiting"; +# trx 2 can delete (5, 100) on master, but not on slave, as on slave trx 1 +# can insert (5, 100) after trx 2 positioned it's cursor. Trx 2 lock is placed +# in waiting queue after trx 1 lock, but its persistent cursor position was +# stored on (100, 10) record in secondary index before suspending. After trx 1 +# is committed, trx 2 will restore persistent cursor position on (100, 10). As +# (100, 5) secondary index record was inserted before (100, 10) in logical +# order, and (100, 10) record is delete-marked, trx 2 just continues scanning. +# +# Note. There can be several records with the same key in unique secondary +# index, but only one of them must be non-delete-marked. That's why when we do +# point query, cursor position is set in the first record in logical order, and +# then records are iterated until either non-delete-marked record is found or +# all records with the same unique fields are iterated. + +# to prepare showing interesting binlog events +--let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1) +--let $binlog_file=query_get_value(SHOW MASTER STATUS, File, 1) +BEGIN; +--send UPDATE t SET sk = 200 WHERE sk = 100; # trx 2 + +--connection con1 +SET DEBUG_SYNC="now WAIT_FOR delete_started_waiting"; +DELETE FROM t WHERE sk=100; # trx 0 +COMMIT; +--disconnect con1 + +--connection con2 +--reap +--disconnect con2 + +--connection con3 +--error 0 +--reap +if (`SELECT ROW_COUNT() > 0`) +{ + --echo unexpected effective UPDATE + --die +} +--echo must be logged in ROW format as the only event of trx 2 (con3) +INSERT INTO t VALUES (11, 101); +COMMIT; +--source include/show_binlog_events.inc +--disconnect con3 + +--connection default +# If the bug is not fixed, we will see the row inserted by trx 1 here. This can +# cause duplicate key error on slave, when some other trx tries in insert row +# with the same secondary key, as was inserted by trx 1, and not deleted by trx +# 2. +SELECT * FROM t; + +--disconnect pause_purge +SET DEBUG_SYNC="RESET"; +DROP TABLE t; +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/binlog/t/load_data_stm_view.test b/mysql-test/suite/binlog/t/load_data_stm_view.test new file mode 100644 index 00000000..9f64b813 --- /dev/null +++ b/mysql-test/suite/binlog/t/load_data_stm_view.test @@ -0,0 +1,24 @@ +# +# MDEV-3940 Server crash or assertion `item->type() == Item::STRING_ITEM' failure on LOAD DATA through a view with statement binary logging +# + +--source include/have_binlog_format_statement.inc + +--write_file $MYSQLTEST_VARDIR/3940.data +1 +EOF + +reset master; + +create table t1 (i int, j int); +create view v1 as select i from t1; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/3940.data' INTO TABLE v1 (i) +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/3940.data' INTO TABLE v1 +select * from v1; +--let $binlog_file = LAST +--source include/show_binlog_events.inc +drop view v1; +drop table t1; +--remove_file $MYSQLTEST_VARDIR/3940.data diff --git a/mysql-test/suite/binlog/t/mysqladmin.test b/mysql-test/suite/binlog/t/mysqladmin.test new file mode 100644 index 00000000..3c2fbc0a --- /dev/null +++ b/mysql-test/suite/binlog/t/mysqladmin.test @@ -0,0 +1,12 @@ +source include/have_binlog_format_statement.inc; +# +# MDEV-12612 mysqladmin --local flush... to use FLUSH LOCAL +# +create user adm@localhost identified by 'foobar'; +grant reload on *.* to adm@localhost; +reset master; +exec $MYSQLADMIN -uadm -pfoobar flush-status; +source include/show_binlog_events.inc; +exec $MYSQLADMIN --local -uadm -pfoobar flush-status; +source include/show_binlog_events.inc; +drop user adm@localhost; diff --git a/mysql-test/suite/binlog/t/read_only.inc b/mysql-test/suite/binlog/t/read_only.inc new file mode 100644 index 00000000..78136b90 --- /dev/null +++ b/mysql-test/suite/binlog/t/read_only.inc @@ -0,0 +1,79 @@ +--echo # +--echo # MDEV-17863 DROP TEMPORARY TABLE creates a transaction in +--echo # binary log on read only server +--echo # MDEV-19074 Improved read_only mode for slaves with +--echo # gtid_strict_mode enabled +--echo # + +create user test@localhost; +grant CREATE TEMPORARY TABLES, DROP, INSERT, SELECT on *.* to test@localhost; +create table t1 (a int) engine=myisam; +insert into t1 values (1),(2); +reset master; + +set global read_only=1; +--echo # Ensure that optimize and analyze doesn't log to binary log +connect (con1,localhost,test,,test); +--error ER_OPTION_PREVENTS_STATEMENT +insert into t1 values(3); +analyze table t1; +check table t1; +repair table t1; +--error ER_OPTION_PREVENTS_STATEMENT +optimize table t1; + +--echo # Ensure that using temporary tables is not logged +create temporary table tmp1 (a int) engine=myisam; +insert into tmp1 values (1),(2); +update tmp1 set a=10 where a=2; +delete from tmp1 where a=1; +create temporary table tmp2 select * from t1; +select * from tmp1; +select * from tmp2; +create temporary table tmp3 like t1; +create or replace temporary table tmp3 like t1; +alter table tmp2 add column (b int); +select * from tmp2; +--error ER_OPTION_PREVENTS_STATEMENT +insert into t1 select a+100 from tmp2; +drop table tmp1,tmp2,tmp3; + +--echo # Clean up test connection +disconnect con1; +connection default; + +--echo # Execute some commands as root that should not be logged +optimize table t1; +repair table t1; + +--echo # Changes to temporary tables created under readonly should not +--echo # be logged +create temporary table tmp4 (a int) engine=myisam; +insert into tmp4 values (1),(2); +create temporary table tmp5 (a int) engine=myisam; +insert into tmp5 select * from tmp4; +alter table tmp5 add column (b int); + +set global read_only=0; + +insert into tmp4 values (3),(4); +insert into tmp5 values (10,3),(11,4); +select * from tmp4; +select * from tmp5; +update tmp4 set a=10 where a=2; +delete from tmp4 where a=1; +create table t2 select * from tmp4; +alter table tmp5 add column (c int); +insert into tmp5 values (20,5,1),(21,5,2); +select * from tmp5; +insert into t1 select a+200 from tmp5; +select * from t1; +drop table tmp4,tmp5; + +--echo # Check what is logged. Only last create select and the insert...select's should be +--echo # row-logged +source include/show_binlog_events.inc; + +--echo # Clean up +drop user test@localhost; +drop table t1,t2; diff --git a/mysql-test/suite/binlog/t/read_only.test b/mysql-test/suite/binlog/t/read_only.test new file mode 100644 index 00000000..14a4650b --- /dev/null +++ b/mysql-test/suite/binlog/t/read_only.test @@ -0,0 +1,2 @@ +--source include/have_binlog_format_mixed_or_row.inc +--source read_only.inc diff --git a/mysql-test/suite/binlog/t/read_only_statement.test b/mysql-test/suite/binlog/t/read_only_statement.test new file mode 100644 index 00000000..a976854f --- /dev/null +++ b/mysql-test/suite/binlog/t/read_only_statement.test @@ -0,0 +1,2 @@ +--source include/have_binlog_format_statement.inc +--source read_only.inc diff --git a/mysql-test/suite/binlog/t/show_concurrent_rotate.test b/mysql-test/suite/binlog/t/show_concurrent_rotate.test new file mode 100644 index 00000000..b5758e3a --- /dev/null +++ b/mysql-test/suite/binlog/t/show_concurrent_rotate.test @@ -0,0 +1,29 @@ +--source include/have_debug.inc +--source include/have_debug_sync.inc +# mere to limit it run rate +--source include/have_binlog_format_row.inc + +connect(con1,localhost,root,,); +FLUSH LOGS; +FLUSH LOGS; +FLUSH LOGS; + +# This forced synchronization pattern ensures con1 will execute its retry +# path. More specifically, con1 should see that the cache of log files it +# creates during SHOW BINARY LOGS becomes invalidated after con2 completes +# RESET MASTER. +SET DEBUG_SYNC= "at_after_lock_index SIGNAL con1_ready WAIT_FOR con1_go"; +--send SHOW BINARY LOGS + +connect(con2,localhost,root,,); +SET DEBUG_SYNC= "now WAIT_FOR con1_ready"; +RESET MASTER; +FLUSH LOGS; +SET DEBUG_SYNC= "now SIGNAL con1_go"; + +--connection con1 +--echo # The correct result must consists of two records +--replace_column 2 # +--reap + +SET debug_sync = 'reset'; diff --git a/mysql-test/suite/binlog/t/start_alter_mysqlbinlog_replay.test b/mysql-test/suite/binlog/t/start_alter_mysqlbinlog_replay.test new file mode 100644 index 00000000..d59456d7 --- /dev/null +++ b/mysql-test/suite/binlog/t/start_alter_mysqlbinlog_replay.test @@ -0,0 +1,61 @@ +# +# MENT-662: Lag Free Alter On Slave +# + +--echo # +--echo # Test verifies replay of binary logs which contain +--echo # SA/RA/CA works fine. +--echo # Generate a binary log with alter events and use mysqlbinlog tool to +--echo # generate a sql file for replay. Source it on an clean master and +--echo # verify the correctness. Use the latest binlog and repeat the same +--echo # process mentioned above and observe replay works fine. +--echo # +--source include/have_log_bin.inc +--source include/have_innodb.inc +--source include/have_binlog_format_statement.inc + +--let $binlog_alter_two_phase= `select @@binlog_alter_two_phase` +set global binlog_alter_two_phase = ON; +set binlog_alter_two_phase = ON; + +create table t1 (f1 int primary key) engine=InnoDB; +create table t2 (f1 int primary key, constraint c1 foreign key (f1) references t1(f1)) engine=innodb; + +--error ER_CANT_CREATE_TABLE +alter table t2 add constraint c1 foreign key (f1) references t1(f1); + +drop table t2, t1; +select @@gtid_binlog_state; +FLUSH LOGS; + +let MYSQLD_DATADIR= `select @@datadir;`; +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/slave_1.sql + +--echo # reset the binlog +RESET MASTER; +--echo # execute the binlog +--exec $MYSQL --port=$MASTER_MYPORT --host=127.0.0.1 -e "source $MYSQLTEST_VARDIR/tmp/slave_1.sql" +SELECT @@gtid_binlog_state; +FLUSH LOGS; +--echo # Replay 1: One more time to simulate S->S case +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/slave_2.sql + +RESET MASTER; +--echo # execute the binlog +--exec $MYSQL --port=$MASTER_MYPORT --host=127.0.0.1 -e "source $MYSQLTEST_VARDIR/tmp/slave_2.sql" +SELECT @@gtid_binlog_state; +FLUSH LOGS; +--echo # Replay 2: One more time to simulate S->S case +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/slave_3.sql +RESET MASTER; +--echo # execute the binlog +--exec $MYSQL --port=$MASTER_MYPORT --host=127.0.0.1 -e "source $MYSQLTEST_VARDIR/tmp/slave_3.sql" +SELECT @@gtid_binlog_state; + +--echo # clean up +remove_file $MYSQLTEST_VARDIR/tmp/slave_1.sql; +remove_file $MYSQLTEST_VARDIR/tmp/slave_2.sql; +remove_file $MYSQLTEST_VARDIR/tmp/slave_3.sql; +RESET MASTER; + +--eval set global binlog_alter_two_phase=$binlog_alter_two_phase diff --git a/mysql-test/suite/binlog/t/temptable_uservar_disconnect-7938.test b/mysql-test/suite/binlog/t/temptable_uservar_disconnect-7938.test new file mode 100644 index 00000000..a1d91e2f --- /dev/null +++ b/mysql-test/suite/binlog/t/temptable_uservar_disconnect-7938.test @@ -0,0 +1,17 @@ +# +# MDEV-7938 MariaDB Crashes Suddenly while writing binlogs +# +--source include/have_log_bin.inc +--source include/have_binlog_format_mixed.inc + +--connect(con1,localhost,root,,) +create table t1 (i int); +create trigger tr after insert on t1 for each row set @b=@a; + +create temporary table tmp like t1; +insert into t1 values (1); +--disconnect con1 + +--connection default +select * from t1; +drop table t1; |