Below is the list of changes that have just been committed into a local
6.0 repository of sven. When sven 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, 2008-04-08 17:26:43+07:00, sven@riska.(none) +18 -0
WL#344: Time-delayed Replication
Implement new CHANGE MASTER TO MASTER_DELAY=X" feature, which causes the
replication slave to be X seconds behind master.
This is a special pre-release commit for Kay :-)
Many result files need to be updated since the output of SHOW SLAVE STATUS
changed.
mysql-test/include/save_master_pos.inc@stripped, 2008-04-08 17:26:39+07:00, sven@riska.(none) +16 -0
Like the test language's built-in save_master_pos, but saves it in a test
language variable so it's accessible to tests.
mysql-test/include/save_master_pos.inc@stripped, 2008-04-08 17:26:39+07:00, sven@riska.(none) +0 -0
mysql-test/include/show_slave_status3.inc@stripped, 2008-04-08 17:26:39+07:00, sven@riska.(none) +8 -0
Like show_slave_status2.inc, but shows Slave_IO_State.
mysql-test/include/show_slave_status3.inc@stripped, 2008-04-08 17:26:39+07:00, sven@riska.(none) +0 -0
mysql-test/include/wait_for_slave_io_to_sync.inc@stripped, 2008-04-08 17:26:39+07:00, sven@riska.(none) +41 -0
Like sync_slave_with_master, but only waits until the IO thread has\
synced; the SQL thread may still be behind.
mysql-test/include/wait_for_slave_io_to_sync.inc@stripped, 2008-04-08 17:26:39+07:00, sven@riska.(none) +0 -0
mysql-test/suite/rpl/r/rpl_delayed_slave.result@stripped, 2008-04-08 17:26:39+07:00, sven@riska.(none) +690 -0
Result file for new test.
mysql-test/suite/rpl/r/rpl_delayed_slave.result@stripped, 2008-04-08 17:26:39+07:00, sven@riska.(none) +0 -0
mysql-test/suite/rpl/t/rpl_delayed_slave.test@stripped, 2008-04-08 17:26:39+07:00, sven@riska.(none) +275 -0
Test to check the new CHANGE MASTER TO MASTER_DELAY = X feature.
mysql-test/suite/rpl/t/rpl_delayed_slave.test@stripped, 2008-04-08 17:26:39+07:00, sven@riska.(none) +0 -0
sql/lex.h@stripped, 2008-04-08 17:26:37+07:00, sven@riska.(none) +1 -0
Add MASTER_DELAY parser symbol.
sql/rpl_mi.cc@stripped, 2008-04-08 17:26:37+07:00, sven@riska.(none) +14 -4
Read and write the delay to file.
sql/rpl_mi.h@stripped, 2008-04-08 17:26:37+07:00, sven@riska.(none) +5 -0
Add delay to Master_info.
sql/rpl_rli.cc@stripped, 2008-04-08 17:26:37+07:00, sven@riska.(none) +3 -5
Make is_fake compiled in unconditionally.
sql/rpl_rli.h@stripped, 2008-04-08 17:26:37+07:00, sven@riska.(none) +7 -3
Make is_fake compiled in unconditionally, add document it.
sql/share/errmsg.txt@stripped, 2008-04-08 17:26:38+07:00, sven@riska.(none) +2 -0
Added parser error message.
sql/slave.cc@stripped, 2008-04-08 17:26:37+07:00, sven@riska.(none) +87 -18
Add Delay to show slave status.
Make sql thread sleep as needed according to the delay.
Change protocol of apply_event_and_update_pos() (we now use rli->is_fake
to determine if we should test if events should be skipped, so the skip
parameter is not needed any more)
Clean up some debug printouts (related to rli->is_fake, which is now
compiled in unconditionally).
sql/slave.h@stripped, 2008-04-08 17:26:37+07:00, sven@riska.(none) +6 -2
change prototype for apply_event_and_update_pos.
sql/sql_binlog.cc@stripped, 2008-04-08 17:26:38+07:00, sven@riska.(none) +2 -4
changed protocol for apply_event_and_update_pos()
made rli->is_fake compiled in unconditionally.
removed initialization of ev->thd from myqsl_client_binlog_statement,
since that is done in apply_event_and_update_pos().
sql/sql_lex.cc@stripped, 2008-04-08 17:26:38+07:00, sven@riska.(none) +9 -0
Added method to zero st_lex_master_info.
sql/sql_lex.h@stripped, 2008-04-08 17:26:38+07:00, sven@riska.(none) +8 -3
Added delay to st_lex_master_info.
Added explicit value to enumeration, since we depend on LEX_MI_UNCHANGED=0
when resetting st_lex_master_info using bzero.
Added set_unspecified() to st_lex_master_info.
sql/sql_repl.cc@stripped, 2008-04-08 17:26:38+07:00, sven@riska.(none) +5 -0
Copy the delay that we parsed from the query to the rli structure.
Add comment explaining what show_binlog_info does.
sql/sql_yacc.yy@stripped, 2008-04-08 17:26:38+07:00, sven@riska.(none) +13 -1
Parse "CHANGE MASTER TO MASTER_DELAY = X"
diff -Nrup a/mysql-test/include/save_master_pos.inc b/mysql-test/include/save_master_pos.inc
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/mysql-test/include/save_master_pos.inc 2008-04-08 17:26:39 +07:00
@@ -0,0 +1,16 @@
+# ==== Purpose ====
+#
+# Saves the master position in the variables
+# $saved_master_file and $saved_master_position.
+#
+# ==== Usage ====
+#
+# source include/save_master_pos.inc;
+#
+# Must be executed on a master.
+#
+# Usually followed by source include/wait_for_slave_io_to_sync.inc; or
+# some other script that uses the saved position.
+
+let $saved_master_file= query_get_value("SHOW MASTER STATUS", File, 1);
+let $saved_master_pos= query_get_value("SHOW MASTER STATUS", Position, 1);
diff -Nrup a/mysql-test/include/show_slave_status3.inc b/mysql-test/include/show_slave_status3.inc
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/mysql-test/include/show_slave_status3.inc 2008-04-08 17:26:39 +07:00
@@ -0,0 +1,8 @@
+# Include file to show the slave status, masking out some information
+# that varies depending on where the test is executed, as well as
+# binlog positions. However, the Slave_IO_State is kept, not masked
+# out.
+
+--replace_result $MASTER_MYPORT MASTER_PORT
+--replace_column 7 # 8 # 9 # 16 # 22 # 23 # 33 # 35 # 36 #
+query_vertical SHOW SLAVE STATUS;
diff -Nrup a/mysql-test/include/wait_for_slave_io_to_sync.inc b/mysql-test/include/wait_for_slave_io_to_sync.inc
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/mysql-test/include/wait_for_slave_io_to_sync.inc 2008-04-08 17:26:39 +07:00
@@ -0,0 +1,41 @@
+# ==== Purpose ====
+#
+# Waits until the slave IO thread has been synced, i.e., all events
+# have been copied over to slave. Does not care if the SQL thread is
+# in sync.
+#
+#
+# ==== Usage ====
+#
+# Syncs the slave to the position saved in the last call to
+# include/save_master_pos.inc.
+#
+# Must be called on the slave.
+
+let $error= `SELECT '$saved_master_pos' = '' OR '$saved_master_file' = ''`;
+if ($error) {
+ --echo ERROR IN TEST SCRIPT: you must source include/save_master_pos.inc before include/wait_for_slave_io_to_sync.inc
+ exit;
+}
+
+let $_counter= 300;
+
+let $_file= query_get_value("SHOW SLAVE STATUS", Master_Log_File, 1);
+let $_pos= query_get_value("SHOW SLAVE STATUS", Read_Master_Log_Pos, 1);
+let $not_done= `SELECT '$_file' != '$saved_master_file' OR '$_pos' != '$saved_master_pos'`;
+
+while ($not_done)
+{
+ dec $_counter;
+ if (!$_counter)
+ {
+ --echo ERROR: failed while waiting for slave io to sync. _file=$_file _pos=$_pos saved_master_file=$saved_master_file saved_master_pos=$saved_master_pos
+ query_vertical show slave status;
+ exit;
+ }
+ sleep 0.1;
+
+ let $_file= query_get_value("SHOW SLAVE STATUS", Master_Log_File, 1);
+ let $_pos= query_get_value("SHOW SLAVE STATUS", Read_Master_Log_Pos, 1);
+ let $not_done= `SELECT '$_file' != '$saved_master_file' OR '$_pos' != '$saved_master_pos'`;
+}
diff -Nrup a/mysql-test/suite/rpl/r/rpl_delayed_slave.result b/mysql-test/suite/rpl/r/rpl_delayed_slave.result
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/mysql-test/suite/rpl/r/rpl_delayed_slave.result 2008-04-08 17:26:39 +07:00
@@ -0,0 +1,690 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+[on master]
+create table t1 (a varchar(100));
+==== Normal setup ====
+[on slave]
+STOP SLAVE;
+CHANGE MASTER TO MASTER_DELAY = 10;
+SHOW SLAVE STATUS;
+Slave_IO_State #
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_PORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos 202
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running No
+Slave_SQL_Running No
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table #
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos 202
+Relay_Log_Space #
+Until_Condition None
+Until_Log_File
+Until_Log_Pos 0
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
+Master_SSL_Verify_Server_Cert No
+Last_IO_Errno #
+Last_IO_Error #
+Last_SQL_Errno 0
+Last_SQL_Error
+Delay 10
+START SLAVE;
+[on master]
+INSERT INTO t1 VALUES ('normal setup');
+[on slave]
+SELECT * FROM t1;
+a
+SHOW SLAVE STATUS;
+Slave_IO_State Waiting for master to send event
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_PORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos #
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running Yes
+Slave_SQL_Running Yes
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table #
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos #
+Relay_Log_Space #
+Until_Condition None
+Until_Log_File
+Until_Log_Pos 0
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
+Master_SSL_Verify_Server_Cert No
+Last_IO_Errno #
+Last_IO_Error #
+Last_SQL_Errno 0
+Last_SQL_Error
+Delay 10
+SELECT * FROM t1;
+a
+SHOW SLAVE STATUS;
+Slave_IO_State Waiting for master to send event
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_PORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos #
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running Yes
+Slave_SQL_Running Yes
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table #
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos #
+Relay_Log_Space #
+Until_Condition None
+Until_Log_File
+Until_Log_Pos 0
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
+Master_SSL_Verify_Server_Cert No
+Last_IO_Errno #
+Last_IO_Error #
+Last_SQL_Errno 0
+Last_SQL_Error
+Delay 10
+==== Slave clock ahead of master ====
+[on master]
+SET TIMESTAMP = 100;
+[on slave]
+STOP SLAVE;
+SET TIMESTAMP = 10100;
+START SLAVE;
+[on master]
+INSERT INTO t1 VALUES ('slave clock ahead of master');
+[on slave]
+SELECT * FROM t1;
+a
+normal setup
+SHOW SLAVE STATUS;
+Slave_IO_State Waiting for master to send event
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_PORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos #
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running Yes
+Slave_SQL_Running Yes
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table #
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos #
+Relay_Log_Space #
+Until_Condition None
+Until_Log_File
+Until_Log_Pos 0
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
+Master_SSL_Verify_Server_Cert No
+Last_IO_Errno #
+Last_IO_Error #
+Last_SQL_Errno 0
+Last_SQL_Error
+Delay 10
+SELECT * FROM t1;
+a
+normal setup
+SHOW SLAVE STATUS;
+Slave_IO_State Waiting for master to send event
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_PORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos #
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running Yes
+Slave_SQL_Running Yes
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table #
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos #
+Relay_Log_Space #
+Until_Condition None
+Until_Log_File
+Until_Log_Pos 0
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
+Master_SSL_Verify_Server_Cert No
+Last_IO_Errno #
+Last_IO_Error #
+Last_SQL_Errno 0
+Last_SQL_Error
+Delay 10
+==== Slave clock behind master ====
+[on master]
+SET TIMESTAMP = 10100;
+[on slave]
+STOP SLAVE;
+SET TIMESTAMP = 100;
+START SLAVE;
+[on master]
+INSERT INTO t1 VALUES ('slave clock behind master');
+[on slave]
+SELECT * FROM t1;
+a
+normal setup
+slave clock ahead of master
+SHOW SLAVE STATUS;
+Slave_IO_State Waiting for master to send event
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_PORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos #
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running Yes
+Slave_SQL_Running Yes
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table #
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos #
+Relay_Log_Space #
+Until_Condition None
+Until_Log_File
+Until_Log_Pos 0
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
+Master_SSL_Verify_Server_Cert No
+Last_IO_Errno #
+Last_IO_Error #
+Last_SQL_Errno 0
+Last_SQL_Error
+Delay 10
+SELECT * FROM t1;
+a
+normal setup
+slave clock ahead of master
+SHOW SLAVE STATUS;
+Slave_IO_State Waiting for master to send event
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_PORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos #
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running Yes
+Slave_SQL_Running Yes
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table #
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos #
+Relay_Log_Space #
+Until_Condition None
+Until_Log_File
+Until_Log_Pos 0
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
+Master_SSL_Verify_Server_Cert No
+Last_IO_Errno #
+Last_IO_Error #
+Last_SQL_Errno 0
+Last_SQL_Error
+Delay 10
+SET TIMESTAMP= 0;
+[on master]
+SET TIMESTAMP= 0;
+==== Slave lags "naturally" after master ====
+INSERT INTO t1 SELECT SLEEP(15);
+INSERT INTO t1 VALUES ('slave lags naturally after master');
+[on slave]
+SELECT * FROM t1;
+a
+normal setup
+slave clock ahead of master
+slave clock behind master
+0
+slave lags naturally after master
+SHOW SLAVE STATUS;
+Slave_IO_State Waiting for master to send event
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_PORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos #
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running Yes
+Slave_SQL_Running Yes
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table #
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos #
+Relay_Log_Space #
+Until_Condition None
+Until_Log_File
+Until_Log_Pos 0
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
+Master_SSL_Verify_Server_Cert No
+Last_IO_Errno #
+Last_IO_Error #
+Last_SQL_Errno 0
+Last_SQL_Error
+Delay 10
+==== STOP SLAVE and START SLAVE ====
+STOP SLAVE;
+CHANGE MASTER TO MASTER_DELAY = 15;
+SHOW SLAVE STATUS;
+Slave_IO_State #
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_PORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos 749
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running No
+Slave_SQL_Running No
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table #
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos 749
+Relay_Log_Space #
+Until_Condition None
+Until_Log_File
+Until_Log_Pos 0
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
+Master_SSL_Verify_Server_Cert No
+Last_IO_Errno #
+Last_IO_Error #
+Last_SQL_Errno 0
+Last_SQL_Error
+Delay 15
+START SLAVE;
+[on master]
+INSERT INTO t1 VALUES ('stop slave and start slave');
+[on slave]
+STOP SLAVE;
+SELECT * FROM t1;
+a
+normal setup
+slave clock ahead of master
+slave clock behind master
+0
+slave lags naturally after master
+SHOW SLAVE STATUS;
+Slave_IO_State
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_PORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos #
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running No
+Slave_SQL_Running No
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table #
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos #
+Relay_Log_Space #
+Until_Condition None
+Until_Log_File
+Until_Log_Pos 0
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
+Master_SSL_Verify_Server_Cert No
+Last_IO_Errno #
+Last_IO_Error #
+Last_SQL_Errno 0
+Last_SQL_Error
+Delay 15
+START SLAVE;
+STOP SLAVE;
+SELECT * FROM t1;
+a
+normal setup
+slave clock ahead of master
+slave clock behind master
+0
+slave lags naturally after master
+SHOW SLAVE STATUS;
+Slave_IO_State
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_PORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos #
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running No
+Slave_SQL_Running No
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table #
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos #
+Relay_Log_Space #
+Until_Condition None
+Until_Log_File
+Until_Log_Pos 0
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
+Master_SSL_Verify_Server_Cert No
+Last_IO_Errno #
+Last_IO_Error #
+Last_SQL_Errno 0
+Last_SQL_Error
+Delay 15
+SELECT * FROM t1;
+a
+normal setup
+slave clock ahead of master
+slave clock behind master
+0
+slave lags naturally after master
+SHOW SLAVE STATUS;
+Slave_IO_State
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_PORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos #
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running No
+Slave_SQL_Running No
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table #
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos #
+Relay_Log_Space #
+Until_Condition None
+Until_Log_File
+Until_Log_Pos 0
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
+Master_SSL_Verify_Server_Cert No
+Last_IO_Errno #
+Last_IO_Error #
+Last_SQL_Errno 0
+Last_SQL_Error
+Delay 15
+==== Change back to no delay ====
+[on master]
+SET TIMESTAMP = 0;
+[on slave]
+SET TIMESTAMP = 0;
+STOP SLAVE;
+Warnings:
+Note 1255 Slave already has been stopped
+CHANGE MASTER TO MASTER_DELAY = 0;
+SHOW SLAVE STATUS;
+Slave_IO_State #
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_PORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos 749
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running No
+Slave_SQL_Running No
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table #
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos 749
+Relay_Log_Space #
+Until_Condition None
+Until_Log_File
+Until_Log_Pos 0
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
+Master_SSL_Verify_Server_Cert No
+Last_IO_Errno #
+Last_IO_Error #
+Last_SQL_Errno 0
+Last_SQL_Error
+Delay 0
+START SLAVE;
+[on master]
+INSERT INTO t1 VALUES ('change back to no delay');
+[on slave]
+SELECT * FROM t1;
+a
+normal setup
+slave clock ahead of master
+slave clock behind master
+0
+slave lags naturally after master
+stop slave and start slave
+change back to no delay
+SHOW SLAVE STATUS;
+Slave_IO_State Waiting for master to send event
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_PORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos #
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running Yes
+Slave_SQL_Running Yes
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table #
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos #
+Relay_Log_Space #
+Until_Condition None
+Until_Log_File
+Until_Log_Pos 0
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
+Master_SSL_Verify_Server_Cert No
+Last_IO_Errno #
+Last_IO_Error #
+Last_SQL_Errno 0
+Last_SQL_Error
+Delay 0
+==== Setting a bad value for the delay ====
+CHANGE MASTER TO MASTER_DELAY = -1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-1' at line 1
+CHANGE MASTER TO MASTER_DELAY = 3000000000;
+ERROR HY000: The requested value for the master delay 3000000000 exceeds the maximum 2147483647
+==== Clean up ====
+[on master]
+drop table t1;
+[on slave]
diff -Nrup a/mysql-test/suite/rpl/t/rpl_delayed_slave.test b/mysql-test/suite/rpl/t/rpl_delayed_slave.test
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/mysql-test/suite/rpl/t/rpl_delayed_slave.test 2008-04-08 17:26:39 +07:00
@@ -0,0 +1,275 @@
+# ==== Purpose ====
+#
+# Test the time-delayed replication feature, i.e.,
+# CHANGE MASTER TO MASTER_DELAY=X:
+#
+# - Verify that slave really has not executed the events before the
+# delay timeout, and that it has executed events after the timout.
+#
+# - Verify that it works when master and slave have different
+# timestamps.
+#
+# - Verify that it works when slave is lagging behind master for
+# "natural" reasons (i.e., slow queries).
+#
+# - Verify that STOP SLAVE works instantly even during a delay, and
+# that it does not cause events to be executed too early on slave.
+#
+# - Verify that changing back to no delay works.
+#
+# ==== Method ====
+#
+# We run the slave with 10 seconds lag.
+#
+# In general, to test that a query has not been executed by the slave
+# before this time, we wait until the slave IO thread has received the
+# event, and then 5 seconds more, and check that the table has not
+# been updated. To test taht a query has been executed after this
+# time, we wait 10 seconds more.
+#
+# To simulate that the slave lags "naturally", we do "select
+# sleep(15)".
+#
+# ==== Related Bugs and Worklogs ====
+#
+# WL#344: Time-delayed replication
+# BUG#28760: Simulating a replication lag
+# [duplicate] BUG#22072: configurable delayed replication
+# [duplicate] BUG#21639: Add Replication Delay parameter
+#
+# ==== Issues with this Test Case ====
+#
+# Relies on all its queries to be executed within 5 seconds.
+#
+# Takes a long time; it sleeps for 90 seconds.
+
+source include/master-slave.inc;
+source include/have_binlog_format_mixed_or_statement.inc;
+
+--echo [on master]
+create table t1 (a varchar(100));
+
+
+--echo ==== Normal setup ====
+
+--echo [on slave]
+sync_slave_with_master;
+STOP SLAVE;
+source include/wait_for_slave_to_stop.inc;
+CHANGE MASTER TO MASTER_DELAY = 10;
+# Master_delay should be 10.
+source include/show_slave_status.inc;
+START SLAVE;
+source include/wait_for_slave_to_start.inc;
+
+--echo [on master]
+connection master;
+INSERT INTO t1 VALUES ('normal setup');
+source include/save_master_pos.inc;
+
+--echo [on slave]
+connection slave;
+source include/wait_for_slave_io_to_sync.inc;
+sleep 5;
+
+# Query should not have been executed.
+SELECT * FROM t1;
+source include/show_slave_status3.inc;
+
+sleep 10;
+
+# Query should have been executed.
+SELECT * FROM t1;
+source include/show_slave_status3.inc;
+
+
+--echo ==== Slave clock ahead of master ====
+
+--echo [on master]
+connection master;
+SET TIMESTAMP = 100;
+
+--echo [on slave]
+connection slave;
+STOP SLAVE;
+source include/wait_for_slave_to_stop.inc;
+SET TIMESTAMP = 10100;
+START SLAVE;
+source include/wait_for_slave_to_start.inc;
+
+--echo [on master]
+connection master;
+INSERT INTO t1 VALUES ('slave clock ahead of master');
+source include/save_master_pos.inc;
+
+--echo [on slave]
+connection slave;
+source include/wait_for_slave_io_to_sync.inc;
+sleep 5;
+
+# Query should not have been executed.
+SELECT * FROM t1;
+source include/show_slave_status3.inc;
+
+sleep 10;
+
+# Query should have been executed.
+SELECT * FROM t1;
+source include/show_slave_status3.inc;
+
+
+--echo ==== Slave clock behind master ====
+
+--echo [on master]
+connection master;
+SET TIMESTAMP = 10100;
+
+--echo [on slave]
+connection slave;
+STOP SLAVE;
+source include/wait_for_slave_to_stop.inc;
+SET TIMESTAMP = 100;
+START SLAVE;
+source include/wait_for_slave_to_start.inc;
+
+--echo [on master]
+connection master;
+INSERT INTO t1 VALUES ('slave clock behind master');
+source include/save_master_pos.inc;
+
+--echo [on slave]
+connection slave;
+source include/wait_for_slave_io_to_sync.inc;
+sleep 5;
+
+# Query should not have been executed.
+SELECT * FROM t1;
+source include/show_slave_status3.inc;
+
+sleep 10;
+
+# Query should have been executed.
+SELECT * FROM t1;
+source include/show_slave_status3.inc;
+
+SET TIMESTAMP= 0;
+--echo [on master]
+connection master;
+SET TIMESTAMP= 0;
+
+
+--echo ==== Slave lags "naturally" after master ====
+
+# To make slave lag, we do a SELECT SLEEP(15) on master
+INSERT INTO t1 SELECT SLEEP(15);
+save_master_pos;
+INSERT INTO t1 VALUES ('slave lags naturally after master');
+source include/save_master_pos.inc;
+
+--echo [on slave]
+connection slave;
+sync_with_master;
+source include/wait_for_slave_io_to_sync.inc;
+sleep 5;
+
+# Query should have been executed.
+SELECT * FROM t1;
+source include/show_slave_status3.inc;
+
+
+--echo ==== STOP SLAVE and START SLAVE ====
+
+# Set up a longer delay.
+STOP SLAVE;
+source include/wait_for_slave_to_stop.inc;
+CHANGE MASTER TO MASTER_DELAY = 15;
+# Master_delay should be 15.
+source include/show_slave_status.inc;
+START SLAVE;
+source include/wait_for_slave_to_start.inc;
+
+--echo [on master]
+connection master;
+INSERT INTO t1 VALUES ('stop slave and start slave');
+
+--echo [on slave]
+connection slave;
+sleep 5;
+STOP SLAVE;
+source include/wait_for_slave_to_stop.inc;
+
+# Query should not have been executed.
+SELECT * FROM t1;
+source include/show_slave_status3.inc;
+
+# Start and stop again, to ensure that even after restarting the
+# slave, we do not execute the event too early.
+START SLAVE;
+source include/wait_for_slave_to_start.inc;
+sleep 5;
+STOP SLAVE;
+source include/wait_for_slave_to_stop.inc;
+
+# Query should not have been executed.
+SELECT * FROM t1;
+source include/show_slave_status3.inc;
+
+sleep 10;
+
+# Query should have been executed.
+SELECT * FROM t1;
+source include/show_slave_status3.inc;
+
+
+--echo ==== Change back to no delay ====
+
+--echo [on master]
+connection master;
+SET TIMESTAMP = 0;
+
+--echo [on slave]
+connection slave;
+SET TIMESTAMP = 0;
+STOP SLAVE;
+source include/wait_for_slave_to_stop.inc;
+CHANGE MASTER TO MASTER_DELAY = 0;
+# Master_delay should be 0.
+source include/show_slave_status.inc;
+START SLAVE;
+source include/wait_for_slave_to_start.inc;
+
+--echo [on master]
+connection master;
+INSERT INTO t1 VALUES ('change back to no delay');
+source include/save_master_pos.inc;
+
+--echo [on slave]
+connection slave;
+source include/wait_for_slave_io_to_sync.inc;
+sleep 5;
+
+# Query should have been executed.
+SELECT * FROM t1;
+source include/show_slave_status3.inc;
+
+
+--echo ==== Setting a bad value for the delay ====
+
+--error ER_PARSE_ERROR
+CHANGE MASTER TO MASTER_DELAY = -1;
+
+--error ER_MASTER_DELAY_VALUE_OUT_OF_RANGE
+CHANGE MASTER TO MASTER_DELAY = 3000000000;
+
+# todo: CHANGE MASTER TO MASTER_DELAY = 999999999999999999999999999
+# should give error
+
+
+--echo ==== Clean up ====
+
+--echo [on master]
+connection master;
+drop table t1;
+
+--echo [on slave]
+sync_slave_with_master;
diff -Nrup a/sql/lex.h b/sql/lex.h
--- a/sql/lex.h 2008-04-01 17:56:38 +07:00
+++ b/sql/lex.h 2008-04-08 17:26:37 +07:00
@@ -306,6 +306,7 @@ static SYMBOL symbols[] = {
{ "LOW_PRIORITY", SYM(LOW_PRIORITY)},
{ "MASTER", SYM(MASTER_SYM)},
{ "MASTER_CONNECT_RETRY", SYM(MASTER_CONNECT_RETRY_SYM)},
+ { "MASTER_DELAY", SYM(MASTER_DELAY_SYM)},
{ "MASTER_HOST", SYM(MASTER_HOST_SYM)},
{ "MASTER_LOG_FILE", SYM(MASTER_LOG_FILE_SYM)},
{ "MASTER_LOG_POS", SYM(MASTER_LOG_POS_SYM)},
diff -Nrup a/sql/rpl_mi.cc b/sql/rpl_mi.cc
--- a/sql/rpl_mi.cc 2008-03-15 05:21:24 +07:00
+++ b/sql/rpl_mi.cc 2008-04-08 17:26:37 +07:00
@@ -33,7 +33,7 @@ Master_info::Master_info()
:Slave_reporting_capability("I/O"),
ssl(0), ssl_verify_server_cert(0), fd(-1), io_thd(0), port(MYSQL_PORT),
connect_retry(DEFAULT_CONNECT_RETRY), heartbeat_period(0),
- received_heartbeats(0), inited(0),
+ received_heartbeats(0), delay(0), inited(0),
abort_slave(0), slave_running(0), slave_run_id(0)
{
host[0] = 0; user[0] = 0; password[0] = 0;
@@ -87,8 +87,11 @@ enum {
/* 6.0 added value of master_heartbeat_period */
LINE_FOR_MASTER_HEARTBEAT_PERIOD= 16,
+ /* 6.0 added value of master_delay */
+ LINE_FOR_MASTER_DELAY= 17,
+
/* Number of lines currently used when saving master info file */
- LINES_IN_MASTER_INFO= LINE_FOR_MASTER_HEARTBEAT_PERIOD
+ LINES_IN_MASTER_INFO= LINE_FOR_MASTER_DELAY
};
@@ -192,6 +195,7 @@ file '%s')", fname);
int port, connect_retry, master_log_pos, lines;
int ssl= 0, ssl_verify_server_cert= 0;
float master_heartbeat_period= 0.0;
+ int delay= 0;
char *first_non_digit;
/*
@@ -280,6 +284,11 @@ file '%s')", fname);
if (lines >= LINE_FOR_MASTER_HEARTBEAT_PERIOD &&
init_floatvar_from_file(&master_heartbeat_period, &mi->file, 0.0))
goto errwithmsg;
+
+ /* Starting from 6.0, delay may be in the file. */
+ if (lines >= LINE_FOR_MASTER_DELAY &&
+ init_intvar_from_file(&delay, &mi->file, 0))
+ goto errwithmsg;
}
#ifndef HAVE_OPENSSL
@@ -381,14 +390,15 @@ int flush_master_info(Master_info* mi, b
my_sprintf(heartbeat_buf, (heartbeat_buf, "%.3f", mi->heartbeat_period));
my_b_seek(file, 0L);
my_b_printf(file,
- "%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n%d\n%s\n",
+ "%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n"
+ "%s\n%d\n%s\n%d\n",
LINES_IN_MASTER_INFO,
mi->master_log_name, llstr(mi->master_log_pos, lbuf),
mi->host, mi->user,
mi->password, mi->port, mi->connect_retry,
(int)(mi->ssl), mi->ssl_ca, mi->ssl_capath, mi->ssl_cert,
mi->ssl_cipher, mi->ssl_key, mi->ssl_verify_server_cert,
- heartbeat_buf);
+ heartbeat_buf, mi->delay);
DBUG_RETURN(-flush_io_cache(file));
}
diff -Nrup a/sql/rpl_mi.h b/sql/rpl_mi.h
--- a/sql/rpl_mi.h 2008-02-03 16:00:47 +07:00
+++ b/sql/rpl_mi.h 2008-04-08 17:26:37 +07:00
@@ -85,6 +85,11 @@ class Master_info : public Slave_reporti
uint connect_retry;
float heartbeat_period; // interface with CHANGE MASTER or master.info
ulonglong received_heartbeats; // counter of received heartbeat events
+ /**
+ Delay replication slave by this amount, compared to master (in
+ seconds). This is set with CHANGE MASTER TO MASTER_DELAY=X.
+ */
+ int delay;
#ifndef DBUG_OFF
int events_till_disconnect;
#endif
diff -Nrup a/sql/rpl_rli.cc b/sql/rpl_rli.cc
--- a/sql/rpl_rli.cc 2008-03-27 17:13:13 +07:00
+++ b/sql/rpl_rli.cc 2008-04-08 17:26:37 +07:00
@@ -33,11 +33,9 @@ Relay_log_info::Relay_log_info()
:Slave_reporting_capability("SQL"),
no_storage(FALSE), replicate_same_server_id(::replicate_same_server_id),
info_fd(-1), cur_log_fd(-1), save_temporary_tables(0),
-#if HAVE_purify
- is_fake(FALSE),
-#endif
- cur_log_old_open_count(0), group_relay_log_pos(0), event_relay_log_pos(0),
- group_master_log_pos(0), log_space_total(0), ignore_log_space_limit(0),
+ cur_log_old_open_count(0), group_relay_log_pos(0),
+ event_relay_log_pos(0), is_fake(FALSE), group_master_log_pos(0),
+ log_space_total(0), ignore_log_space_limit(0),
last_master_timestamp(0), slave_skip_counter(0),
abort_pos_wait(0), slave_run_id(0), sql_thd(0),
inited(0), abort_slave(0), slave_running(0), until_condition(UNTIL_NONE),
diff -Nrup a/sql/rpl_rli.h b/sql/rpl_rli.h
--- a/sql/rpl_rli.h 2008-03-27 16:56:03 +07:00
+++ b/sql/rpl_rli.h 2008-04-08 17:26:37 +07:00
@@ -154,9 +154,13 @@ public:
ulonglong event_relay_log_pos;
ulonglong future_event_relay_log_pos;
-#ifdef HAVE_purify
- bool is_fake; /* Mark that this is a fake relay log info structure */
-#endif
+ /*
+ False for the Relay_log_info object that belongs to the io thread
+ and sql thread; true for the Relay_log_info that belongs to a
+ client. In other words, non-fake rli's are used for replication,
+ whereas fake ones are used to execute BINLOG statements.
+ */
+ bool is_fake;
/*
Original log name and position of the group we're currently executing
diff -Nrup a/sql/share/errmsg.txt b/sql/share/errmsg.txt
--- a/sql/share/errmsg.txt 2008-04-03 01:48:16 +07:00
+++ b/sql/share/errmsg.txt 2008-04-08 17:26:38 +07:00
@@ -6252,3 +6252,5 @@ ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE
eng "The requested value for the heartbeat period %s %s"
ER_LOG_PURGE_NO_FILE
eng "Being purged log %s was not found"
+ER_MASTER_DELAY_VALUE_OUT_OF_RANGE
+ eng "The requested value for the master delay %u exceeds the maximum %u"
diff -Nrup a/sql/slave.cc b/sql/slave.cc
--- a/sql/slave.cc 2008-04-01 17:56:42 +07:00
+++ b/sql/slave.cc 2008-04-08 17:26:37 +07:00
@@ -1171,6 +1171,9 @@ int register_slave_on_master(MYSQL* mysq
}
+/**
+ Called to execute SHOW SLAVE STATUS.
+*/
bool show_master_info(THD* thd, Master_info* mi)
{
// TODO: fix this for multi-master
@@ -1238,6 +1241,8 @@ bool show_master_info(THD* thd, Master_i
field_list.push_back(new Item_empty_string("Last_IO_Error", 20));
field_list.push_back(new Item_return_int("Last_SQL_Errno", 4, MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Last_SQL_Error", 20));
+ field_list.push_back(new Item_return_int("Delay", 10,
+ MYSQL_TYPE_LONG));
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
@@ -1357,6 +1362,8 @@ bool show_master_info(THD* thd, Master_i
protocol->store(mi->rli.last_error().number);
// Last_SQL_Error
protocol->store(mi->rli.last_error().message, &my_charset_bin);
+ // Delay
+ protocol->store((uint32) mi->delay);
pthread_mutex_unlock(&mi->rli.data_lock);
pthread_mutex_unlock(&mi->data_lock);
@@ -1680,21 +1687,36 @@ static int has_temporary_error(THD *thd)
/**
Applies the given event and advances the relay log position.
- In essence, this function does:
+ Conceptually, this function does:
@code
ev->apply_event(rli);
ev->update_pos(rli);
@endcode
- But it also does some maintainance, such as skipping events if
- needed and reporting errors.
+ It also does the following maintainance:
+
+ - Initializes the thread's server_id and time; and the event's
+ thread.
+
+ - If rli is not fake (i.e., if it belongs to the slave threads
+ instead of being used for executing BINLOG statements), it does
+ three things: (1) skips events if it is needed according to the
+ server id or slave_skip_counter; (2) sleeps appropriately if this
+ is a time-delayed slave (specified by CHANGE MASTER TO
+ MASTER_DELAY=X); (3) unlocks rli->data_lock.
- If the @c skip flag is set, then it is tested whether the event
- should be skipped, by looking at the slave_skip_counter and the
- server id. The skip flag should be set when calling this from a
- replication thread but not set when executing an explicit BINLOG
- statement.
+ - Reports errors as needed.
+
+ @param ev The event to apply.
+
+ @param thd The client thread that executes the event (i.e., the
+ slave sql thread if called from a replication slave, or the client
+ thread if called to execute a BINLOG statement).
+
+ @param rli The relay log info (i.e., the slave's rli if called from
+ a replication slave, or the client's thd->rli_fake if called to
+ execute a BINLOG statement).
@retval 0 OK.
@@ -1703,8 +1725,7 @@ static int has_temporary_error(THD *thd)
@retval 2 No error calling ev->apply_event(), but error calling
ev->update_pos().
*/
-int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli,
- bool skip)
+int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli)
{
int exec_res= 0;
@@ -1749,14 +1770,58 @@ int apply_event_and_update_pos(Log_event
ev->when= my_time(0);
ev->thd = thd; // because up to this point, ev->thd == 0
- if (skip)
+ /*
+ There is one non-"fake" rli object for the slave threads, and one
+ "fake" rli object for executing explicit BINLOG statements.
+ Below, the slave does three things that should not be done by
+ BINLOG statements:
+
+ (1) checks if the event shall be skipped,
+
+ (2) unlocks rli->data_lock.
+
+ (3) honors the delay specified by CHANGE MASTER TO MASTER_DELAY=X,
+ */
+ if (!rli->is_fake)
{
+ // (1) Check if we need to skip the event.
int reason= ev->shall_skip(rli);
if (reason == Log_event::EVENT_SKIP_COUNT)
--rli->slave_skip_counter;
+
+ // (2) unlock rli->data_lock
pthread_mutex_unlock(&rli->data_lock);
+
+ // (2) If event should be executed, check if slave needs to delay.
if (reason == Log_event::EVENT_SKIP_NOT)
+ {
+ Master_info *mi= rli->mi;
+ long delay= mi->delay;
+ if (delay)
+ {
+ time_t now= my_time(0);
+ /*
+ X=when+clock_diff is the event time converted to the slave's clock.
+ Y=now-X is the time we are already delayed.
+ nap_time=delay-Y is the remaining time to delay
+ */
+ long nap_time= delay - (now - (ev->when + mi->clock_diff_with_master));
+ DBUG_PRINT("info", ("ev->when= %lu mi->clock_diff_with_master= %lu "
+ "now= %lu delay= %lu nap_time= %lu",
+ (long)ev->when, mi->clock_diff_with_master,
+ (long)now, delay, nap_time));
+
+ if (nap_time > 0)
+ {
+ DBUG_PRINT("info", ("delaying replication event %lu secs",
+ nap_time));
+ safe_sleep(thd, nap_time, (CHECK_KILLED_FUNC)sql_slave_killed,
+ (void*)rli);
+ }
+ }
exec_res= ev->apply_event(rli);
+ }
+
#ifndef DBUG_OFF
/*
This only prints information to the debug trace.
@@ -1785,14 +1850,11 @@ int apply_event_and_update_pos(Log_event
if (exec_res == 0)
{
int error= ev->update_pos(rli);
-#ifdef HAVE_purify
+#ifndef DBUG_OFF
+ DBUG_PRINT("info", ("update_pos error = %d", error));
if (!rli->is_fake)
-#endif
{
-#ifndef DBUG_OFF
char buf[22];
-#endif
- DBUG_PRINT("info", ("update_pos error = %d", error));
DBUG_PRINT("info", ("group %s %s",
llstr(rli->group_relay_log_pos, buf),
rli->group_relay_log_name));
@@ -1800,6 +1862,7 @@ int apply_event_and_update_pos(Log_event
llstr(rli->event_relay_log_pos, buf),
rli->event_relay_log_name));
}
+#endif
/*
The update should not fail, so print an error message and
return an error code.
@@ -1845,7 +1908,7 @@ int apply_event_and_update_pos(Log_event
fewer times, 0 is returned.
- init_master_info or init_relay_log_pos failed. (These are called
- if a failure occurs when applying the event.)</li>
+ if a failure occurs when applying the event.)
- An error occurred when updating the binlog position.
@@ -1899,7 +1962,7 @@ static int exec_relay_log_event(THD* thd
delete ev;
DBUG_RETURN(1);
}
- exec_res= apply_event_and_update_pos(ev, thd, rli, TRUE);
+ exec_res= apply_event_and_update_pos(ev, thd, rli);
/*
Format_description_log_event should not be deleted because it will be
@@ -3536,6 +3599,12 @@ static IO_CACHE *reopen_relay_log(Relay_
}
+/**
+ Reads next event from the relay log. Should be called from the
+ slave IO thread.
+
+ @return The event read, or NULL on error.
+*/
static Log_event* next_event(Relay_log_info* rli)
{
Log_event* ev;
diff -Nrup a/sql/slave.h b/sql/slave.h
--- a/sql/slave.h 2008-03-30 14:17:07 +07:00
+++ b/sql/slave.h 2008-04-08 17:26:37 +07:00
@@ -33,6 +33,11 @@
*/
#define SLAVE_MAX_HEARTBEAT_PERIOD 4294967
+/**
+ MASTER_DELAY can be at most INT32_MAX.
+*/
+#define MASTER_DELAY_MAX (0X7FFFFFFF)
+
#ifdef HAVE_REPLICATION
#include "log.h"
@@ -198,8 +203,7 @@ int purge_relay_logs(Relay_log_info* rli
void set_slave_thread_options(THD* thd);
void set_slave_thread_default_charset(THD *thd, Relay_log_info const *rli);
void rotate_relay_log(Master_info* mi);
-int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli,
- bool skip);
+int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli);
pthread_handler_t handle_slave_io(void *arg);
pthread_handler_t handle_slave_sql(void *arg);
diff -Nrup a/sql/sql_binlog.cc b/sql/sql_binlog.cc
--- a/sql/sql_binlog.cc 2008-03-05 17:19:53 +07:00
+++ b/sql/sql_binlog.cc 2008-04-08 17:26:38 +07:00
@@ -56,9 +56,7 @@ void mysql_client_binlog_statement(THD*
if (!thd->rli_fake)
{
thd->rli_fake= new Relay_log_info;
-#ifdef HAVE_purify
thd->rli_fake->is_fake= TRUE;
-#endif
have_fd_event= FALSE;
}
if (thd->rli_fake && !thd->rli_fake->relay_log.description_event_for_exec)
@@ -196,7 +194,7 @@ void mysql_client_binlog_statement(THD*
bytes_decoded, (long) bufptr,
(ulong) uint4korr(bufptr+EVENT_LEN_OFFSET)));
#endif
- ev->thd= thd;
+
/*
We go directly to the application phase, since we don't need
to check if the event shall be skipped or not.
@@ -206,7 +204,7 @@ void mysql_client_binlog_statement(THD*
reporting.
*/
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
- if (apply_event_and_update_pos(ev, thd, thd->rli_fake, FALSE))
+ if (apply_event_and_update_pos(ev, thd, thd->rli_fake))
{
/*
TODO: Maybe a better error message since the BINLOG statement
diff -Nrup a/sql/sql_lex.cc b/sql/sql_lex.cc
--- a/sql/sql_lex.cc 2008-04-01 17:56:44 +07:00
+++ b/sql/sql_lex.cc 2008-04-08 17:26:38 +07:00
@@ -3028,3 +3028,12 @@ bool st_lex::is_partition_management() c
alter_info.flags == ALTER_REORGANIZE_PARTITION));
}
+
+/**
+ Set all fields to their "unspecified" value.
+*/
+void st_lex_master_info::set_unspecified()
+{
+ bzero((char*) this, sizeof(*this));
+ delay= -1;
+}
diff -Nrup a/sql/sql_lex.h b/sql/sql_lex.h
--- a/sql/sql_lex.h 2008-04-01 17:56:44 +07:00
+++ b/sql/sql_lex.h 2008-04-08 17:26:38 +07:00
@@ -200,17 +200,22 @@ typedef struct st_lex_master_info
char *host, *user, *password, *log_file_name;
uint port, connect_retry;
float heartbeat_period;
+ int delay;
ulonglong pos;
ulong server_id;
/*
Enum is used for making it possible to detect if the user
- changed variable or if it should be left at old value
- */
- enum {LEX_MI_UNCHANGED, LEX_MI_DISABLE, LEX_MI_ENABLE}
+ changed variable or if it should be left at old value.
+ LEX_MI_UNCHANGED must be 0 since we use bzero to reset these
+ variables in set_undefined().
+ */
+ enum {LEX_MI_UNCHANGED= 0, LEX_MI_DISABLE, LEX_MI_ENABLE}
ssl, ssl_verify_server_cert, heartbeat_opt;
char *ssl_key, *ssl_cert, *ssl_ca, *ssl_capath, *ssl_cipher;
char *relay_log_name;
ulong relay_log_pos;
+
+ void set_unspecified();
} LEX_MASTER_INFO;
diff -Nrup a/sql/sql_repl.cc b/sql/sql_repl.cc
--- a/sql/sql_repl.cc 2008-03-08 17:14:45 +07:00
+++ b/sql/sql_repl.cc 2008-04-08 17:26:38 +07:00
@@ -1259,6 +1259,8 @@ bool change_master(THD* thd, Master_info
mi->heartbeat_period= (float) min(SLAVE_MAX_HEARTBEAT_PERIOD,
(slave_net_timeout/2.0));
mi->received_heartbeats= LL(0); // counter lives until master is CHANGEd
+ if (lex_mi->delay != -1)
+ mi->delay= lex_mi->delay;
if (lex_mi->ssl != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
mi->ssl= (lex_mi->ssl == LEX_MASTER_INFO::LEX_MI_ENABLE);
@@ -1587,6 +1589,9 @@ err:
}
+/**
+ Called to execute SHOW MASTER STATUS queries.
+*/
bool show_binlog_info(THD* thd)
{
Protocol *protocol= thd->protocol;
diff -Nrup a/sql/sql_yacc.yy b/sql/sql_yacc.yy
--- a/sql/sql_yacc.yy 2008-04-01 20:19:00 +07:00
+++ b/sql/sql_yacc.yy 2008-04-08 17:26:38 +07:00
@@ -876,6 +876,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
%token LOW_PRIORITY
%token LT /* OPERATOR */
%token MASTER_CONNECT_RETRY_SYM
+%token MASTER_DELAY_SYM
%token MASTER_HOST_SYM
%token MASTER_LOG_FILE_SYM
%token MASTER_LOG_POS_SYM
@@ -1635,7 +1636,7 @@ change:
{
LEX *lex = Lex;
lex->sql_command = SQLCOM_CHANGE_MASTER;
- bzero((char*) &lex->mi, sizeof(lex->mi));
+ lex->mi.set_unspecified();
}
master_defs
{}
@@ -1667,6 +1668,16 @@ master_def:
{
Lex->mi.connect_retry = $3;
}
+ | MASTER_DELAY_SYM EQ ulong_num
+ {
+ if ($3 > MASTER_DELAY_MAX)
+ {
+ my_error(ER_MASTER_DELAY_VALUE_OUT_OF_RANGE, MYF(0),
+ $3, MASTER_DELAY_MAX);
+ }
+ else
+ Lex->mi.delay = $3;
+ }
| MASTER_SSL_SYM EQ ulong_num
{
Lex->mi.ssl= $3 ?
@@ -11018,6 +11029,7 @@ keyword_sp:
| MASTER_PASSWORD_SYM {}
| MASTER_SERVER_ID_SYM {}
| MASTER_CONNECT_RETRY_SYM {}
+ | MASTER_DELAY_SYM {}
| MASTER_SSL_SYM {}
| MASTER_SSL_CA_SYM {}
| MASTER_SSL_CAPATH_SYM {}
| Thread |
|---|
| • bk commit into 6.0 tree (sven:1.2626) WL#344 | Sven Sandberg | 8 Apr |