mirror of
https://github.com/MariaDB/server.git
synced 2025-01-20 14:02:32 +01:00
f56d77dadf
The bug allow multiple executing transactions working with non-transactional to interfere with each others by interleaving the events of different trans- actions. Bug is fixed by writing non-transactional events to the transaction cache and flushing the cache to the binary log at statement commit. To mimic the behavior of normal statement-based replication, we flush the transaction cache in row- based mode when there is no committed statements in the transaction cache, which means we are committing the first one. This means that it will be written to the binary log as a "mini-transaction" with just the rows for the statement. Note that the changes here does not take effect when building the server with HAVE_TRANSACTIONS set to false, but it is not clear if this was possible before this patch either. For row-based logging, we also have that when AUTOCOMMIT=1, the code now always generates a BEGIN/COMMIT pair for single statements, or BEGIN/ROLLBACK pair in the case of non-transactional changes in a statement that was rolled back. Note that for the case where changes to a non-transactional table causes a rollback due to error, the statement will now be logged with a BEGIN/ROLLBACK pair, even though some changes has been committed to the non-transactional table. mysql-test/extra/rpl_tests/rpl_row_delayed_ins.test: Removing SHOW BINLOG EVENTS causing test to be non-deterministic. mysql-test/r/ctype_cp932_binlog_row.result: Result change. mysql-test/suite/binlog/r/binlog_base64_flag.result: Result change. mysql-test/suite/binlog/r/binlog_multi_engine.result: Result file change. mysql-test/suite/binlog/r/binlog_row_binlog.result: Result file change. mysql-test/suite/binlog/r/binlog_row_ctype_ucs.result: Result file change. mysql-test/suite/binlog/r/binlog_row_insert_select.result: Result file change. mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result: Result file change. mysql-test/suite/binlog/r/binlog_stm_binlog.result: Result file change. mysql-test/suite/binlog/t/binlog_base64_flag.test: Removing table that will be used in test to prevent failing if preceeding tests forgot to drop the table. mysql-test/suite/rpl/r/rpl_rbr_to_sbr.result: Result file change. mysql-test/suite/rpl/r/rpl_row_basic_11bugs.result: Result file change. mysql-test/suite/rpl/r/rpl_row_create_table.result: Result file change. mysql-test/suite/rpl/r/rpl_row_delayed_ins.result: Result file change. mysql-test/suite/rpl/r/rpl_row_flsh_tbls.result: Result file change. mysql-test/suite/rpl/r/rpl_row_inexist_tbl.result: Result file change. mysql-test/suite/rpl/r/rpl_row_log.result: Result file change. mysql-test/suite/rpl/r/rpl_row_log_innodb.result: Result file change. mysql-test/suite/rpl/r/rpl_row_until.result: Result file change. mysql-test/suite/rpl/r/rpl_slave_skip.result: Result file change. mysql-test/suite/rpl/r/rpl_switch_stm_row_mixed.result: Result file change. mysql-test/suite/rpl/r/rpl_truncate_2myisam.result: Result file change. mysql-test/suite/rpl/t/rpl_row_create_table.test: Binlog position change. mysql-test/suite/rpl/t/rpl_row_flsh_tbls.test: Binlog position change. mysql-test/suite/rpl/t/rpl_row_mysqlbinlog.test: Binlog position change. Added stop position to mysqlbinlog argments to prevent extreneous output. mysql-test/suite/rpl/t/rpl_row_until.test: Binlog position change. mysql-test/suite/rpl/t/rpl_slave_skip.test: Binlog position change. mysql-test/suite/rpl/t/rpl_switch_stm_row_mixed.test: Removing extreneous SHOW BINLOG EVENTS causing test to be non-deterministic. mysql-test/suite/rpl_ndb/r/rpl_ndb_log.result: Result change. sql/log.cc: Adding variable at_least_one_stmt to denote that there is at least one statement committed to the transaction cache (but there might be more). Removing duplicate checks from binlog_end_trans(). The transaction cache should always be committed or rolled back when this function is called. Correcting conditions for binlog_rollback() and binlog_commit() and removing the previous "invisible commit" in favor of always using explicit commits in the binary log. sql/log_event.cc: Marking table map event to be cached. Removing Muted_query_log_event from code. sql/log_event.h: Removing unused class Muted_query_log_event. sql/sql_insert.cc: Adding missing call to ha_autocommit_or_rollback() for delayed thread. Marking CREATE-SELECT statements as transactional, since they don't need to be logged.
354 lines
11 KiB
Text
354 lines
11 KiB
Text
##################################################################
|
||
# Author: JBM #
|
||
# Date: 2006-02-22 #
|
||
# Purpose: To test changes to mysqlbinlog for row based bin logs #
|
||
# We are using .opt file since we need small binlog size #
|
||
##################################################################
|
||
# Include Section
|
||
# Make sure that we have row based bin log
|
||
-- source include/have_binlog_format_row.inc
|
||
# Embedded server doesn't support binlogging
|
||
-- source include/not_embedded.inc
|
||
-- source include/master-slave.inc
|
||
# This test requires the cp932 charset compiled in
|
||
-- source include/have_cp932.inc
|
||
|
||
# Setup Section
|
||
# we need this for getting fixed timestamps inside of this test
|
||
|
||
--disable_query_log
|
||
select "---Setup Section --" as "";
|
||
--enable_query_log
|
||
|
||
set timestamp=1000000000;
|
||
|
||
--disable_warnings
|
||
DROP TABLE IF EXISTS t1,t2,t3;
|
||
--enable_warnings
|
||
|
||
connection master;
|
||
CREATE TABLE t1(word VARCHAR(20));
|
||
CREATE TABLE t2(id INT AUTO_INCREMENT NOT NULL PRIMARY KEY);
|
||
CREATE TABLE t3(c1 INT NOT NULL PRIMARY KEY, c2 LONGBLOB, c3 TIMESTAMP, c4 TEXT, c5 FLOAT);
|
||
|
||
|
||
# Test Section
|
||
# Lets start by putting some data into the tables.
|
||
|
||
--disable_query_log
|
||
INSERT INTO t1 VALUES ("abirvalg");
|
||
LOAD DATA INFILE '../std_data_ln/words.dat' INTO TABLE t1;
|
||
LOAD DATA INFILE '../std_data_ln/words.dat' INTO TABLE t1;
|
||
LOAD DATA INFILE '../std_data_ln/words.dat' INTO TABLE t1;
|
||
LOAD DATA INFILE '../std_data_ln/words.dat' INTO TABLE t1;
|
||
LOAD DATA INFILE '../std_data_ln/words.dat' INTO TABLE t1;
|
||
|
||
# d1 length 3000
|
||
set @d1 = 'dd1';
|
||
set @d1 = concat(@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1);
|
||
set @d1 = concat(@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1);
|
||
set @d1 = concat(@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1);
|
||
|
||
let $count=500;
|
||
while ($count)
|
||
{
|
||
INSERT INTO t2 VALUES (NULL);
|
||
eval INSERT INTO t3 VALUES ($count,@d1,'20060222000000','Tested in Texas',$count*2.2);
|
||
dec $count;
|
||
}
|
||
--enable_query_log
|
||
|
||
|
||
--disable_query_log
|
||
select "---Test1 check table load --" as "";
|
||
--enable_query_log
|
||
|
||
# Lets Check the tables on the Master
|
||
SELECT COUNT(*) from t1;
|
||
SELECT COUNT(*) from t2;
|
||
SELECT COUNT(*) from t3;
|
||
SELECT * FROM t1 ORDER BY word LIMIT 5;
|
||
SELECT * FROM t2 ORDER BY id LIMIT 5;
|
||
SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5;
|
||
|
||
# Should have the same on the slave;
|
||
|
||
sync_slave_with_master;
|
||
SELECT COUNT(*) from t1;
|
||
SELECT COUNT(*) from t2;
|
||
SELECT COUNT(*) from t3;
|
||
SELECT * FROM t1 ORDER BY word LIMIT 5;
|
||
SELECT * FROM t2 ORDER BY id LIMIT 5;
|
||
SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5;
|
||
|
||
# Okay time to get busy, back to master
|
||
|
||
connection master;
|
||
|
||
# simple query to show more in second binlog
|
||
insert into t1 values ("Alas");
|
||
flush logs;
|
||
|
||
# delimiters are for easier debugging in future
|
||
--disable_query_log
|
||
select "--- Test 1 Dump binlog to file --" as "";
|
||
--enable_query_log
|
||
|
||
#
|
||
# Prepare local temporary file to recreate what we have currently.
|
||
|
||
--exec $MYSQL_BINLOG $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/master.sql
|
||
|
||
--exec $MYSQL_BINLOG $MYSQLTEST_VARDIR/log/master-bin.000002 >> $MYSQLTEST_VARDIR/tmp/master.sql
|
||
|
||
# Now that we have our file, lets get rid of the current database.
|
||
# Cleanup the master and the slave and try to recreate.
|
||
--disable_query_log
|
||
select "--- Test 1 delete tables, clean master and slave --" as "";
|
||
--enable_query_log
|
||
|
||
DROP TABLE t1;
|
||
DROP TABLE t2;
|
||
DROP TABLE t3;
|
||
|
||
sync_slave_with_master;
|
||
#we expect STOP SLAVE to produce a warning as the slave is stopped
|
||
#(the server was started with skip-slave-start)
|
||
--disable_warnings
|
||
stop slave;
|
||
--enable_warnings
|
||
--require r/slave-stopped.result
|
||
show status like 'Slave_running';
|
||
connection master;
|
||
reset master;
|
||
connection slave;
|
||
reset slave;
|
||
start slave;
|
||
--require r/slave-running.result
|
||
show status like 'Slave_running';
|
||
connection master;
|
||
|
||
# We should be clean at this point, now we will run in the file from above.
|
||
--disable_query_log
|
||
select "--- Test 1 Load from Dump binlog file --" as "";
|
||
--enable_query_log
|
||
|
||
--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/master.sql"
|
||
|
||
--disable_query_log
|
||
select "--- Test 1 Check Load Results --" as "";
|
||
--enable_query_log
|
||
|
||
# Lets Check the tables on the Master
|
||
SELECT COUNT(*) from t1;
|
||
SELECT COUNT(*) from t2;
|
||
SELECT COUNT(*) from t3;
|
||
SELECT * FROM t1 ORDER BY word LIMIT 5;
|
||
SELECT * FROM t2 ORDER BY id LIMIT 5;
|
||
SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5;
|
||
|
||
# Should have the same on the slave;
|
||
|
||
sync_slave_with_master;
|
||
SELECT COUNT(*) from t1;
|
||
SELECT COUNT(*) from t2;
|
||
SELECT COUNT(*) from t3;
|
||
SELECT * FROM t1 ORDER BY word LIMIT 5;
|
||
SELECT * FROM t2 ORDER BY id LIMIT 5;
|
||
SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5;
|
||
connection master;
|
||
|
||
# We should be gold by the time, so I will get rid of our file.
|
||
|
||
--exec rm $MYSQLTEST_VARDIR/tmp/master.sql
|
||
|
||
|
||
# this test for position option
|
||
# By setting this position to 416, we should only get the create of t3
|
||
--disable_query_log
|
||
select "--- Test 2 position test --" as "";
|
||
--enable_query_log
|
||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||
--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --position=416 --stop-position=569 $MYSQLTEST_VARDIR/log/master-bin.000001
|
||
|
||
# These are tests for remote binlog.
|
||
# They should return the same as previous test.
|
||
|
||
--disable_query_log
|
||
select "--- Test 3 First Remote test --" as "";
|
||
--enable_query_log
|
||
|
||
# This is broken now
|
||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||
--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --stop-position=569 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
|
||
|
||
# This part is disabled due to bug #17654
|
||
|
||
--disable_query_log
|
||
select "--- Test 4 Second Remote test --" as "";
|
||
--enable_query_log
|
||
--exec $MYSQL_BINLOG --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 > $MYSQLTEST_VARDIR/tmp/remote.sql
|
||
|
||
--exec $MYSQL_BINLOG --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002 >> $MYSQLTEST_VARDIR/tmp/remote.sql
|
||
|
||
# Now that we have our file, lets get rid of the current database.
|
||
# Cleanup the master and the slave and try to recreate.
|
||
|
||
DROP TABLE t1;
|
||
DROP TABLE t2;
|
||
DROP TABLE t3;
|
||
|
||
sync_slave_with_master;
|
||
|
||
#we expect STOP SLAVE to produce a warning as the slave is stopped
|
||
#(the server was started with skip-slave-start)
|
||
|
||
--disable_warnings
|
||
stop slave;
|
||
--enable_warnings
|
||
--require r/slave-stopped.result
|
||
show status like 'Slave_running';
|
||
connection master;
|
||
reset master;
|
||
connection slave;
|
||
reset slave;
|
||
start slave;
|
||
--require r/slave-running.result
|
||
show status like 'Slave_running';
|
||
connection master;
|
||
|
||
# We should be clean at this point, now we will run in the file from above.
|
||
|
||
--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/remote.sql"
|
||
|
||
# Lets Check the tables on the Master
|
||
|
||
SELECT COUNT(*) from t1;
|
||
SELECT COUNT(*) from t2;
|
||
SELECT COUNT(*) from t3;
|
||
SELECT * FROM t1 ORDER BY word LIMIT 5;
|
||
SELECT * FROM t2 ORDER BY id LIMIT 5;
|
||
SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5;
|
||
|
||
# Should have the same on the slave;
|
||
|
||
sync_slave_with_master;
|
||
SELECT COUNT(*) from t1;
|
||
SELECT COUNT(*) from t2;
|
||
SELECT COUNT(*) from t3;
|
||
SELECT * FROM t1 ORDER BY word LIMIT 5;
|
||
SELECT * FROM t2 ORDER BY id LIMIT 5;
|
||
SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5;
|
||
connection master;
|
||
|
||
# We should be gold by the time, so I will get rid of our file.
|
||
|
||
--exec rm $MYSQLTEST_VARDIR/tmp/remote.sql
|
||
################### End Bug 17654 ######################
|
||
|
||
# What is the point of this test? It seems entirely pointless. It
|
||
# might make sense for statement-based replication, but for row-based
|
||
# replication the LOAD DATA INFILE is printed just as empty
|
||
# transactions. /Matz
|
||
|
||
# LOAD DATA
|
||
--disable_query_log
|
||
select "--- Test 5 LOAD DATA --" as "";
|
||
--enable_query_log
|
||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||
--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --stop-position=106 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002
|
||
|
||
# Bug#7853 (mysqlbinlog does not accept input from stdin)
|
||
|
||
--disable_query_log
|
||
select "--- Test 6 reading stdin --" as "";
|
||
--enable_query_log
|
||
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
|
||
--exec $MYSQL_BINLOG --short-form --stop-position=569 - < $MYSQLTEST_VARDIR/log/master-bin.000001
|
||
|
||
--disable_query_log
|
||
select "--- Test 7 reading stdin w/position --" as "";
|
||
--enable_query_log
|
||
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
|
||
--exec $MYSQL_BINLOG --short-form --position=416 --stop-position=569 - < $MYSQLTEST_VARDIR/log/master-bin.000001
|
||
|
||
# Bug#16217 (mysql client did not know how not switch its internal charset)
|
||
--disable_query_log
|
||
select "--- Test 8 switch internal charset --" as "";
|
||
--enable_query_log
|
||
sync_slave_with_master;
|
||
|
||
#we expect STOP SLAVE to produce a warning as the slave is stopped
|
||
#(the server was started with skip-slave-start)
|
||
|
||
--disable_warnings
|
||
stop slave;
|
||
--enable_warnings
|
||
--require r/slave-stopped.result
|
||
show status like 'Slave_running';
|
||
connection master;
|
||
reset master;
|
||
connection slave;
|
||
reset slave;
|
||
start slave;
|
||
--require r/slave-running.result
|
||
show status like 'Slave_running';
|
||
connection master;
|
||
|
||
create table t4 (f text character set utf8);
|
||
create table t5 (f text character set cp932);
|
||
--exec $MYSQL --default-character-set=utf8 test -e "insert into t4 values(_utf8'ソ')"
|
||
--exec $MYSQL --default-character-set=cp932 test -e "insert into t5 values(_cp932'<27>\');"
|
||
flush logs;
|
||
rename table t4 to t04, t5 to t05;
|
||
--exec $MYSQL_BINLOG $MYSQLTEST_VARDIR/log/master-bin.000001 | $MYSQL --default-character-set=utf8
|
||
# original and recovered data must be equal
|
||
select HEX(f) from t04;
|
||
select HEX(f) from t4;
|
||
select HEX(f) from t05;
|
||
select HEX(f) from t5;
|
||
|
||
# slave should have same
|
||
sync_slave_with_master;
|
||
select HEX(f) from t04;
|
||
select HEX(f) from t4;
|
||
select HEX(f) from t05;
|
||
select HEX(f) from t5;
|
||
|
||
--disable_query_log
|
||
select "--- Test cleanup --" as "";
|
||
--enable_query_log
|
||
# clean up
|
||
connection master;
|
||
sync_slave_with_master;
|
||
|
||
connection master;
|
||
|
||
# BUG#17654 also test mysqlbinlog to ensure it can read the binlog from a remote server
|
||
# and ensure that the results are the same as if read from a file (the same file).
|
||
|
||
--disable_warnings
|
||
DROP TABLE IF EXISTS t1;
|
||
--enable_warnings
|
||
|
||
CREATE TABLE t1 (a INT NOT NULL KEY, b INT);
|
||
|
||
INSERT INTO t1 VALUES(1,1);
|
||
|
||
SELECT * FROM t1;
|
||
|
||
FLUSH LOGS;
|
||
|
||
--exec $MYSQL_BINLOG --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 > $MYSQLTEST_VARDIR/tmp/remote.sql
|
||
--exec $MYSQL_BINLOG $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/local.sql
|
||
|
||
--diff_files $MYSQLTEST_VARDIR/tmp/local.sql $MYSQLTEST_VARDIR/tmp/remote.sql
|
||
|
||
--exec rm $MYSQLTEST_VARDIR/tmp/remote.sql
|
||
|
||
--exec rm $MYSQLTEST_VARDIR/tmp/local.sql
|
||
|
||
DROP TABLE IF EXISTS t1, t2, t3, t04, t05, t4, t5;
|
||
sync_slave_with_master;
|
||
|
||
# End of 4.1 tests
|