List:Commits« Previous MessageNext Message »
From:Mats Kindahl Date:December 20 2007 3:07pm
Subject:bk commit into 5.0 tree (mats:1.2557) BUG#12691
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of mats. When mats does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-12-20 16:07:54+01:00, mats@stripped +3 -0
  BUG#12691 (Exec_master_log_pos corrupted with SQL_SLAVE_SKIP_COUNTER):
  
  Complementary patch since LOAD DATA INFILE was not covered in
  the previous patch.
  
  This patch adds a check so that the slave skip counter is not
  decreased to zero if seeing a BEGIN_LOAD_QUERY_EVENT,
  APPEND_BLOCK_EVENT, or CREATE_FILE_EVENT since these cannot
  end a group. The group is terminated by an EXECUTE_LOAD_QUERY_
  EVENT or DELETE_FILE_EVENT.

  mysql-test/r/rpl_slave_skip.result@stripped, 2007-12-20 16:07:51+01:00, mats@stripped +101 -3
    Result change.

  mysql-test/t/rpl_slave_skip.test@stripped, 2007-12-20 16:07:51+01:00, mats@stripped +166 -3
    Adding tests to test that the first event of a LOAD DATA INFILE
    can be skipped safely for both transactional and non-transactional
    tables. Also include a case that will generate a DELETE_FILE event
    last in the group, and this should be properly skipped as well.

  sql/slave.cc@stripped, 2007-12-20 16:07:52+01:00, mats@stripped +4 -1
    Not decrementing slave skip counter to zero when seeing a
    BEGIN_LOAD_QUERY_EVENT, APPEND_BLOCK_EVENT, or CREATE_FILE_EVENT
    since these cannot end a group.

diff -Nrup a/mysql-test/r/rpl_slave_skip.result b/mysql-test/r/rpl_slave_skip.result
--- a/mysql-test/r/rpl_slave_skip.result	2007-10-26 18:52:53 +02:00
+++ b/mysql-test/r/rpl_slave_skip.result	2007-12-20 16:07:51 +01:00
@@ -5,8 +5,10 @@ reset slave;
 drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
 start slave;
 **** On Master ****
-CREATE TABLE t1 (a INT, b SET('master','slave')) ENGINE=INNODB;
-CREATE TABLE t2 (a INT, b SET('master','slave')) ENGINE=MYISAM;
+CREATE TABLE t1 (a INT, b SET('master','slave')) ENGINE=InnoDB;
+CREATE TABLE t2 (a INT, b SET('master','slave')) ENGINE=MyISAM;
+CREATE TABLE t3 (a CHAR(20), b SET('master','slave')) ENGINE=InnoDB;
+CREATE TABLE t4 (a CHAR(20), b SET('master','slave')) ENGINE=MyISAM;
 ==== Skipping normal transactions ==== 
 **** On Slave ****
 STOP SLAVE;
@@ -139,6 +141,102 @@ a	b
 SELECT * FROM t2 ORDER BY a;
 a	b
 5	master,slave
+==== Skipping first event of a LOAD DATA for a transactional table ==== 
+**** On Slave ****
+STOP SLAVE;
+**** On Master ****
+SET AUTOCOMMIT=1;
+LOAD DATA INFILE '../std_data_ln/words.dat' INTO TABLE t3(a) SET b = 'master';
+INSERT INTO t3 VALUES ('Go Rin No Sho', 'master,slave');
+SELECT COUNT(*) FROM t3;
+COUNT(*)
+71
+**** On Slave ****
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
+START SLAVE;
+-- Should only contain records marked 'master,slave'
+SELECT * FROM t3 ORDER BY a;
+a	b
+Go Rin No Sho	master,slave
+**** On Master ****
+DELETE FROM t3;
+==== Skipping first event of a LOAD DATA for a non-transactional table ==== 
+**** On Slave ****
+STOP SLAVE;
+**** On Master ****
+SET AUTOCOMMIT=1;
+LOAD DATA INFILE '../std_data_ln/words.dat' INTO TABLE t4(a) SET b = 'master';
+INSERT INTO t4 VALUES ('Go Rin No Sho', 'master,slave');
+SELECT COUNT(*) FROM t4;
+COUNT(*)
+71
+**** On Slave ****
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
+START SLAVE;
+-- Should only contain records marked 'master,slave'
+SELECT * FROM t4 ORDER BY a;
+a	b
+Go Rin No Sho	master,slave
+**** On Master ****
+DELETE FROM t4;
+==== Try with a big file so that we get an append_block event as well
+**** On Slave ****
+STOP SLAVE;
+**** On Master ****
+SET AUTOCOMMIT=1;
+SET SQL_LOG_BIN=0;
+LOAD DATA INFILE '../std_data_ln/words.dat' INTO TABLE t4(a) SET b = 'master';
+INSERT INTO t4 SELECT * FROM t4;
+INSERT INTO t4 SELECT * FROM t4;
+INSERT INTO t4 SELECT * FROM t4;
+INSERT INTO t4 SELECT * FROM t4;
+INSERT INTO t4 SELECT * FROM t4;
+INSERT INTO t4 SELECT * FROM t4;
+INSERT INTO t4 SELECT * FROM t4;
+INSERT INTO t4 SELECT * FROM t4;
+INSERT INTO t4 SELECT * FROM t4;
+INSERT INTO t4 SELECT * FROM t4;
+INSERT INTO t4 SELECT * FROM t4;
+SELECT a FROM t4 INTO OUTFILE 'rpl_slave_skip_words.dat';
+SET SQL_LOG_BIN=1;
+LOAD DATA INFILE 'rpl_slave_skip_words.dat' INTO TABLE t4(a) SET b = 'master';
+INSERT INTO t4 VALUES ('Go Rin No Sho', 'master,slave');
+SELECT COUNT(*) FROM t4;
+COUNT(*)
+286721
+**** On Slave ****
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
+START SLAVE;
+-- Should only contain records marked 'master,slave'
+SELECT * FROM t4 ORDER BY a;
+a	b
+Go Rin No Sho	master,slave
+**** On Master ****
+DELETE FROM t4;
+**** On Master ****
+CREATE TABLE t5 (a int, b int, c SET('master','slave'), PRIMARY KEY (a,b)) ENGINE=MyISAM;
+LOAD DATA INFILE '../std_data_ln/loaddata5.dat' INTO TABLE t5 FIELDS TERMINATED BY '' ENCLOSED BY '' (a,b) SET c='master,slave';
+**** On Slave ****
+STOP SLAVE;
+**** On Master ****
+LOAD DATA INFILE '../std_data_ln/loaddata5.dat' INTO TABLE t5 FIELDS TERMINATED BY '' ENCLOSED BY '' (a,b) SET c='';
+ERROR 23000: Duplicate entry '1-2' for key 1
+INSERT INTO t5 VALUES (42, 42, 'master,slave');
+SELECT * FROM t5;
+a	b	c
+1	2	master,slave
+3	4	master,slave
+5	6	master,slave
+42	42	master,slave
+**** On Slave ****
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
+START SLAVE;
+SELECT * FROM t5;
+a	b	c
+1	2	master,slave
+3	4	master,slave
+5	6	master,slave
+42	42	master,slave
 ==== Cleanup ==== 
 **** On Master ****
-DROP TABLE t1, t2;
+DROP TABLE t1, t2, t3, t4, t5;
diff -Nrup a/mysql-test/t/rpl_slave_skip.test b/mysql-test/t/rpl_slave_skip.test
--- a/mysql-test/t/rpl_slave_skip.test	2007-10-26 18:52:54 +02:00
+++ b/mysql-test/t/rpl_slave_skip.test	2007-12-20 16:07:51 +01:00
@@ -13,8 +13,10 @@ source include/master-slave.inc;
 # it back to get the non-transactional change into the table.
 
 --echo **** On Master ****
-CREATE TABLE t1 (a INT, b SET('master','slave')) ENGINE=INNODB;
-CREATE TABLE t2 (a INT, b SET('master','slave')) ENGINE=MYISAM;
+CREATE TABLE t1 (a INT, b SET('master','slave')) ENGINE=InnoDB;
+CREATE TABLE t2 (a INT, b SET('master','slave')) ENGINE=MyISAM;
+CREATE TABLE t3 (a CHAR(20), b SET('master','slave')) ENGINE=InnoDB;
+CREATE TABLE t4 (a CHAR(20), b SET('master','slave')) ENGINE=MyISAM;
 
 --echo ==== Skipping normal transactions ==== 
 
@@ -195,9 +197,170 @@ sync_with_master;
 SELECT * FROM t1 ORDER BY a;
 SELECT * FROM t2 ORDER BY a;
 
+--echo ==== Skipping first event of a LOAD DATA for a transactional table ==== 
+
+--echo **** On Slave ****
+connection slave;
+STOP SLAVE;
+source include/wait_for_slave_to_stop.inc;
+
+--echo **** On Master ****
+connection master;
+SET AUTOCOMMIT=1;
+
+LOAD DATA INFILE '../std_data_ln/words.dat' INTO TABLE t3(a) SET b = 'master';
+INSERT INTO t3 VALUES ('Go Rin No Sho', 'master,slave');
+
+save_master_pos;
+
+SELECT COUNT(*) FROM t3;
+
+# This will skip a begin event and the first INSERT of the
+# transaction, and it should keep skipping until it has reached the
+# transaction terminator.
+
+--echo **** On Slave ****
+connection slave;
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
+START SLAVE;
+source include/wait_for_slave_to_start.inc;
+sync_with_master;
+--echo -- Should only contain records marked 'master,slave'
+SELECT * FROM t3 ORDER BY a;
+
+--echo **** On Master ****
+connection master;
+DELETE FROM t3;
+sync_slave_with_master;
+
+--echo ==== Skipping first event of a LOAD DATA for a non-transactional table ==== 
+
+--echo **** On Slave ****
+connection slave;
+STOP SLAVE;
+source include/wait_for_slave_to_stop.inc;
+
+--echo **** On Master ****
+connection master;
+SET AUTOCOMMIT=1;
+
+LOAD DATA INFILE '../std_data_ln/words.dat' INTO TABLE t4(a) SET b = 'master';
+INSERT INTO t4 VALUES ('Go Rin No Sho', 'master,slave');
+
+save_master_pos;
+
+SELECT COUNT(*) FROM t4;
+
+# This will skip a begin event and the first INSERT of the
+# transaction, and it should keep skipping until it has reached the
+# transaction terminator.
+
+--echo **** On Slave ****
+connection slave;
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
+START SLAVE;
+source include/wait_for_slave_to_start.inc;
+sync_with_master;
+--echo -- Should only contain records marked 'master,slave'
+SELECT * FROM t4 ORDER BY a;
+
+--echo **** On Master ****
+connection master;
+DELETE FROM t4;
+sync_slave_with_master;
+
+--echo ==== Try with a big file so that we get an append_block event as well
+
+--echo **** On Slave ****
+connection slave;
+STOP SLAVE;
+source include/wait_for_slave_to_stop.inc;
+
+--echo **** On Master ****
+connection master;
+SET AUTOCOMMIT=1;
+
+# This contain about 70 words, so we double it a few times to get more than 128 KiB
+SET SQL_LOG_BIN=0;
+LOAD DATA INFILE '../std_data_ln/words.dat' INTO TABLE t4(a) SET b = 'master';
+INSERT INTO t4 SELECT * FROM t4;
+INSERT INTO t4 SELECT * FROM t4;
+INSERT INTO t4 SELECT * FROM t4;
+INSERT INTO t4 SELECT * FROM t4;
+INSERT INTO t4 SELECT * FROM t4;
+INSERT INTO t4 SELECT * FROM t4;
+INSERT INTO t4 SELECT * FROM t4;
+INSERT INTO t4 SELECT * FROM t4;
+INSERT INTO t4 SELECT * FROM t4;
+INSERT INTO t4 SELECT * FROM t4;
+INSERT INTO t4 SELECT * FROM t4;
+SELECT a FROM t4 INTO OUTFILE 'rpl_slave_skip_words.dat';
+SET SQL_LOG_BIN=1;
+
+# Start the real job
+LOAD DATA INFILE 'rpl_slave_skip_words.dat' INTO TABLE t4(a) SET b = 'master';
+INSERT INTO t4 VALUES ('Go Rin No Sho', 'master,slave');
+
+#SHOW BINLOG EVENTS;
+
+save_master_pos;
+
+SELECT COUNT(*) FROM t4;
+
+# This will skip a begin event and the first INSERT of the
+# transaction, and it should keep skipping until it has reached the
+# transaction terminator.
+
+--echo **** On Slave ****
+connection slave;
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
+START SLAVE;
+source include/wait_for_slave_to_start.inc;
+sync_with_master;
+--echo -- Should only contain records marked 'master,slave'
+SELECT * FROM t4 ORDER BY a;
+
+--echo **** On Master ****
+connection master;
+DELETE FROM t4;
+sync_slave_with_master;
+
+# Test to generate a Delete_file log event, and see that it works as well.
+--echo **** On Master ****
+connection master;
+CREATE TABLE t5 (a int, b int, c SET('master','slave'), PRIMARY KEY (a,b)) ENGINE=MyISAM;
+LOAD DATA INFILE '../std_data_ln/loaddata5.dat' INTO TABLE t5 FIELDS TERMINATED BY '' ENCLOSED BY '' (a,b) SET c='master,slave';
+
+--echo **** On Slave ****
+sync_slave_with_master;
+STOP SLAVE;
+source include/wait_for_slave_to_stop.inc;
+
+--echo **** On Master ****
+connection master;
+error ER_DUP_ENTRY;
+LOAD DATA INFILE '../std_data_ln/loaddata5.dat' INTO TABLE t5 FIELDS TERMINATED BY '' ENCLOSED BY '' (a,b) SET c='';
+INSERT INTO t5 VALUES (42, 42, 'master,slave');
+save_master_pos;
+
+#SHOW BINLOG EVENTS;
+
+SELECT * FROM t5;
+
+--echo **** On Slave ****
+connection slave;
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
+START SLAVE;
+source include/wait_for_slave_to_start.inc;
+
+sync_with_master;
+SELECT * FROM t5;
+
+connection slave;
+
 --echo ==== Cleanup ==== 
 
 --echo **** On Master ****
 connection master;
-DROP TABLE t1, t2;
+DROP TABLE t1, t2, t3, t4, t5;
 sync_slave_with_master;
diff -Nrup a/sql/slave.cc b/sql/slave.cc
--- a/sql/slave.cc	2007-10-26 19:17:55 +02:00
+++ b/sql/slave.cc	2007-12-20 16:07:52 +01:00
@@ -3348,7 +3348,10 @@ static int exec_relay_log_event(THD* thd
       if (rli->slave_skip_counter &&
           !((type_code == INTVAR_EVENT ||
              type_code == RAND_EVENT ||
-             type_code == USER_VAR_EVENT) &&
+             type_code == USER_VAR_EVENT ||
+             type_code == BEGIN_LOAD_QUERY_EVENT ||
+             type_code == APPEND_BLOCK_EVENT ||
+             type_code == CREATE_FILE_EVENT) &&
             rli->slave_skip_counter == 1) &&
 #if MYSQL_VERSION_ID < 50100
           /*
Thread
bk commit into 5.0 tree (mats:1.2557) BUG#12691Mats Kindahl30 Dec