MDEV-7145: Delayed replication
Merge feature into 10.2 from feature branch. Delayed replication adds an option CHANGE MASTER TO master_delay=<seconds> Replication will then delay applying events with that many seconds. This creates a replication slave that reflects the state of the master some time in the past. Feature is ported from MySQL source tree. Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org>
This commit is contained in:
commit
e1ef99c3dc
55
mysql-test/extra/rpl_tests/delayed_slave_wait_on_query.inc
Normal file
55
mysql-test/extra/rpl_tests/delayed_slave_wait_on_query.inc
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# ==== Purpose ====
|
||||||
|
#
|
||||||
|
# Auxiliary file used by rpl_delayed_slave.test. This assumes that an
|
||||||
|
# 'INSERT INTO t1...' query has been executed on the master. It does
|
||||||
|
# this:
|
||||||
|
#
|
||||||
|
# - After half the delay, check the status. It should be delaying and
|
||||||
|
# the query should not have executed.
|
||||||
|
#
|
||||||
|
# - After one and a half delay, check the status. It should not be
|
||||||
|
# delaying and the query should be executed.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# ==== Usage ====
|
||||||
|
#
|
||||||
|
# --let $query_number= 4
|
||||||
|
# --source extra/rpl_tests/delayed_slave_wait_on_query.inc
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
# $query_number
|
||||||
|
# The value of the 'b' column in t1 for the row inserted by the query
|
||||||
|
# we are waiting for.
|
||||||
|
|
||||||
|
connection master;
|
||||||
|
|
||||||
|
--echo [on slave]
|
||||||
|
--let $slave_timeout= $time1
|
||||||
|
--source include/sync_slave_io_with_master.inc
|
||||||
|
--echo # sleep 1*T
|
||||||
|
--sleep $time1
|
||||||
|
|
||||||
|
--let $assert_text= Query $query_number should not be executed
|
||||||
|
--let $assert_cond= MAX(b) < $query_number FROM t1
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--let $assert_text= Status should be 'Waiting until MASTER_DELAY...'
|
||||||
|
--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" LIKE "Waiting until MASTER_DELAY%"
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--echo # sleep 1*T
|
||||||
|
--sleep $time1
|
||||||
|
|
||||||
|
--echo # sync with master (with timeout 1*T)
|
||||||
|
--source include/sync_with_master.inc
|
||||||
|
|
||||||
|
--let $assert_text= Query $query_number should be executed
|
||||||
|
--let $assert_cond= MAX(b) = $query_number FROM t1
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--let $assert_text= Status should be 'Has read all relay log...'
|
||||||
|
--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" LIKE "Slave has read all relay log%"
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
|
||||||
|
--source include/check_slave_is_running.inc
|
@ -67,6 +67,9 @@ if ($tmp)
|
|||||||
--echo Replicate_Do_Domain_Ids
|
--echo Replicate_Do_Domain_Ids
|
||||||
--echo Replicate_Ignore_Domain_Ids
|
--echo Replicate_Ignore_Domain_Ids
|
||||||
--echo Parallel_Mode conservative
|
--echo Parallel_Mode conservative
|
||||||
|
--echo SQL_Delay 0
|
||||||
|
--echo SQL_Remaining_Delay NULL
|
||||||
|
--echo Slave_SQL_Running_State
|
||||||
}
|
}
|
||||||
if (!$tmp) {
|
if (!$tmp) {
|
||||||
# Note: after WL#5177, fields 13-18 shall not be filtered-out.
|
# Note: after WL#5177, fields 13-18 shall not be filtered-out.
|
||||||
|
@ -101,16 +101,16 @@ if ($relocate_index_file)
|
|||||||
--eval LOAD DATA INFILE '$relocate_fix_relay_log_info' INTO TABLE tmp (entry)
|
--eval LOAD DATA INFILE '$relocate_fix_relay_log_info' INTO TABLE tmp (entry)
|
||||||
--let $count= `SELECT count(*) FROM tmp`
|
--let $count= `SELECT count(*) FROM tmp`
|
||||||
|
|
||||||
--let $_curr_entry= `SELECT entry FROM tmp WHERE id=1`
|
--let $_curr_entry= `SELECT entry FROM tmp WHERE id=2`
|
||||||
--let $_curr_entry_basename= `SELECT RIGHT(RTRIM("$_curr_entry"), LOCATE("$_path_separator",REVERSE(RTRIM("$_curr_entry"))) -1)`
|
--let $_curr_entry_basename= `SELECT RIGHT(RTRIM("$_curr_entry"), LOCATE("$_path_separator",REVERSE(RTRIM("$_curr_entry"))) -1)`
|
||||||
|
|
||||||
if ($relocate_is_windows)
|
if ($relocate_is_windows)
|
||||||
{
|
{
|
||||||
--eval UPDATE tmp SET entry='$_to\$_curr_entry_basename' WHERE id=1
|
--eval UPDATE tmp SET entry='$_to\$_curr_entry_basename' WHERE id=2
|
||||||
}
|
}
|
||||||
if (!$relocate_is_windows)
|
if (!$relocate_is_windows)
|
||||||
{
|
{
|
||||||
--eval UPDATE tmp SET entry='$_to/$_curr_entry_basename' WHERE id=1
|
--eval UPDATE tmp SET entry='$_to/$_curr_entry_basename' WHERE id=2
|
||||||
}
|
}
|
||||||
|
|
||||||
--remove_file $relocate_fix_relay_log_info
|
--remove_file $relocate_fix_relay_log_info
|
||||||
|
118
mysql-test/include/rpl_assert.inc
Normal file
118
mysql-test/include/rpl_assert.inc
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
# ==== Purpose ====
|
||||||
|
#
|
||||||
|
# Check if a condition holds, fail with debug info if not.
|
||||||
|
#
|
||||||
|
# The condition is parsed before executed. The following constructs
|
||||||
|
# are supported:
|
||||||
|
#
|
||||||
|
# [SQL STATEMENT, COLUMN, ROW]
|
||||||
|
# The square bracket is replaced by the result from SQL STATEMENT,
|
||||||
|
# in the given COLUMN and ROW.
|
||||||
|
#
|
||||||
|
# <1>
|
||||||
|
# This is a shorthand for the result of the first executed square
|
||||||
|
# bracket. <2> is a shorthand for the second executed square
|
||||||
|
# bracket, and so on.
|
||||||
|
#
|
||||||
|
# ==== Usage ====
|
||||||
|
#
|
||||||
|
# --let $assert_text= Relay_Log_Pos must be smaller than pos.
|
||||||
|
# --let $assert_cond= [SHOW SLAVE STATUS, Relay_Log_Pos, 1] >= $min_pos AND <1> <= $max_pos
|
||||||
|
# [--let $assert_quiet= 1]
|
||||||
|
# [--let $rpl_debug= 1]
|
||||||
|
# --source include/rpl_assert.inc
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
#
|
||||||
|
# $assert_text
|
||||||
|
# Text that describes what is being checked. By default, this text
|
||||||
|
# is written to the query log.
|
||||||
|
#
|
||||||
|
# $assert_cond
|
||||||
|
# Condition to check. See above for details about the format. The
|
||||||
|
# condition will be executed as `SELECT $assert_cond`. Note: this
|
||||||
|
# condition is parsed using SQL statements, quoted inside single
|
||||||
|
# quotes, so it must not contain single quotes itself (use double
|
||||||
|
# quotes for strings).
|
||||||
|
#
|
||||||
|
# $assert_quiet
|
||||||
|
# Do not print $assert_text to the query log.
|
||||||
|
#
|
||||||
|
# $rpl_debug
|
||||||
|
# Print extra debug info.
|
||||||
|
|
||||||
|
|
||||||
|
if ($rpl_debug)
|
||||||
|
{
|
||||||
|
--echo # debug: assert_text='$assert_text' assert_cond='$assert_cond'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Sanity-check input
|
||||||
|
if (`SELECT "$assert_text" = ""`)
|
||||||
|
{
|
||||||
|
--die ERROR IN TEST: the mysqltest variable rpl_test must be set
|
||||||
|
}
|
||||||
|
|
||||||
|
# Evaluate square brackets in cond.
|
||||||
|
--let $_rpl_assert_substmt_number= 1
|
||||||
|
--let $_rpl_interpolated_cond= $assert_cond
|
||||||
|
--let $_rpl_assert_lbracket= `SELECT LOCATE('[', '$_rpl_interpolated_cond')`
|
||||||
|
while ($_rpl_assert_lbracket)
|
||||||
|
{
|
||||||
|
# Get position of right bracket
|
||||||
|
--let $_rpl_assert_rbracket= `SELECT LOCATE(']', '$_rpl_interpolated_cond')`
|
||||||
|
if (!$_rpl_assert_rbracket)
|
||||||
|
{
|
||||||
|
--echo BUG IN TEST: Mismatching square brackets in assert_cond: '$assert_cond'
|
||||||
|
--die BUG IN TEST: Mismatching square brackets in $assert_cond
|
||||||
|
}
|
||||||
|
# Get sub-statement and result of it
|
||||||
|
--let $_rpl_assert_substmt= `SELECT SUBSTRING('$_rpl_interpolated_cond', $_rpl_assert_lbracket + 1, $_rpl_assert_rbracket - $_rpl_assert_lbracket - 1)`
|
||||||
|
--let $_rpl_assert_substmt_result= query_get_value($_rpl_assert_substmt)
|
||||||
|
if ($rpl_debug)
|
||||||
|
{
|
||||||
|
--echo # debug: sub-statement='$_rpl_assert_substmt' result='$rpl_assert_result'
|
||||||
|
}
|
||||||
|
# Replace sub-statement by its result
|
||||||
|
--let $_rpl_interpolated_cond= `SELECT REPLACE('$_rpl_interpolated_cond', '[$_rpl_assert_substmt]', '$_rpl_assert_substmt_result')`
|
||||||
|
# Replace result references by result
|
||||||
|
--let $_rpl_interpolated_cond= `SELECT REPLACE('$_rpl_interpolated_cond', '<$_rpl_assert_substmt_number>', '$_rpl_assert_substmt_result')`
|
||||||
|
|
||||||
|
--let $_rpl_assert_lbracket= `SELECT LOCATE('[', '$_rpl_interpolated_cond')`
|
||||||
|
|
||||||
|
--inc $_rpl_assert_substmt_number
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($rpl_debug)
|
||||||
|
{
|
||||||
|
--echo # debug: interpolated_cond='$_rpl_interpolated_cond'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Execute.
|
||||||
|
--let $_rpl_assert_result= `SELECT $_rpl_interpolated_cond`
|
||||||
|
|
||||||
|
if ($rpl_debug)
|
||||||
|
{
|
||||||
|
--echo # debug: result='$_rpl_assert_result'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check.
|
||||||
|
if (!$_rpl_assert_result)
|
||||||
|
{
|
||||||
|
--echo ######## Test assertion failed: $assert_text ########
|
||||||
|
--echo Dumping debug info:
|
||||||
|
--source include/show_rpl_debug_info.inc
|
||||||
|
--echo Assertion text: '$assert_text'
|
||||||
|
--echo Assertion condition: '$assert_cond'
|
||||||
|
--echo Assertion condition, interpolated: '$_rpl_interpolated_cond'
|
||||||
|
--echo Assertion result: '$_rpl_assert_result'
|
||||||
|
--die Test assertion failed in rpl_assertion.inc
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$assert_quiet)
|
||||||
|
{
|
||||||
|
--echo # Asserted this: $assert_text
|
||||||
|
}
|
||||||
|
|
||||||
|
--let $assert_text=
|
||||||
|
--let $assert_cond=
|
28
mysql-test/include/show_delayed_slave_state.inc
Normal file
28
mysql-test/include/show_delayed_slave_state.inc
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# ==== Purpose ====
|
||||||
|
#
|
||||||
|
# Display the delay state of the SQL thread.
|
||||||
|
#
|
||||||
|
# ==== Usage ====
|
||||||
|
#
|
||||||
|
# --let $verbose_delayed_slave_state= [0|1]
|
||||||
|
# --source extra/rpl_tests/show_delayed_slave_state.inc
|
||||||
|
#
|
||||||
|
# By default, the output is normalized so that it does not depend on
|
||||||
|
# exact timing or exact binlog positions. If
|
||||||
|
# $verbose_delayed_slave_state is set, then it outputs exact times and
|
||||||
|
# binlog positions. This can be useful for debugging.
|
||||||
|
|
||||||
|
--let $_delayed_slave_status= query_get_value(SHOW SLAVE STATUS, Slave_SQL_Running_State, 1)
|
||||||
|
|
||||||
|
--let $_delayed_slave_remaining_delay= query_get_value(SHOW SLAVE STATUS, SQL_Remaining_Delay, 1)
|
||||||
|
--let $_delayed_slave_qualitative_delay= `SELECT CASE WHEN "$_delayed_slave_remaining_delay" = "NULL" THEN "NULL" WHEN "$_delayed_slave_remaining_delay" = "0" THEN "0" ELSE "greater than zero" END`
|
||||||
|
|
||||||
|
--let $_delayed_slave_io_pos= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1)
|
||||||
|
--let $_delayed_slave_sql_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1)
|
||||||
|
--let $_delayed_slave_qualitative_log_pos= `SELECT IF($_delayed_slave_io_pos > $_delayed_slave_sql_pos, "behind", "in sync with")`
|
||||||
|
|
||||||
|
--echo Slave_SQL_Running_State='$_delayed_slave_status'; SQL_Remaining_Delay is $_delayed_slave_qualitative_delay; SQL thread is $_delayed_slave_qualitative_log_pos IO thread
|
||||||
|
|
||||||
|
if ($verbose_delayed_slave_state) {
|
||||||
|
--echo SQL_Remaining_Delay='$_delayed_slave_remaining_delay'; Read_master_log_pos='$_delayed_slave_io_pos'; Exec_Master_Log_Pos='$_delayed_slave_sql_pos'
|
||||||
|
}
|
26
mysql-test/include/sync_with_master.inc
Normal file
26
mysql-test/include/sync_with_master.inc
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# ==== Purpose ====
|
||||||
|
#
|
||||||
|
# This file does the same as the built-in command sync_with_master,
|
||||||
|
# but can be configured to use a custom timeout. This has the benefit
|
||||||
|
# that it accepts the same $slave_timeout and $master_connection
|
||||||
|
# parameters as wait_for_slave_param.inc
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# ==== Usage ====
|
||||||
|
#
|
||||||
|
# --connection master
|
||||||
|
# --source include/save_master_pos.inc
|
||||||
|
# --connection slave
|
||||||
|
# --source include/sync_with_master.inc
|
||||||
|
#
|
||||||
|
# Parameters to this macro are $slave_timeout and
|
||||||
|
# $master_connection. See wait_for_slave_param.inc for
|
||||||
|
# descriptions.
|
||||||
|
|
||||||
|
--let $slave_param= Relay_Master_Log_File
|
||||||
|
--let $slave_param_value= $_master_file
|
||||||
|
--source include/wait_for_slave_param.inc
|
||||||
|
|
||||||
|
--let $slave_param= Exec_Master_Log_Pos
|
||||||
|
--let $slave_param_value= $_master_pos
|
||||||
|
--source include/wait_for_slave_param.inc
|
@ -89,17 +89,17 @@ MASTER 2.2
|
|||||||
# EOF
|
# EOF
|
||||||
#
|
#
|
||||||
show all slaves status;
|
show all slaves status;
|
||||||
Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos
|
Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos
|
||||||
Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 <read_master_log_pos> relay.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 1 No conservative 0 1073741824 7 0 60.000
|
Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 <read_master_log_pos> relay.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 1 No conservative 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 1073741824 7 0 60.000
|
||||||
MASTER 2.2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> relay-master@00202@002e2.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space2> None 0 No 0 No 0 0 2 No conservative 0 1073741824 7 0 60.000
|
MASTER 2.2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> relay-master@00202@002e2.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space2> None 0 No 0 No 0 0 2 No conservative 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 1073741824 7 0 60.000
|
||||||
include/wait_for_slave_to_start.inc
|
include/wait_for_slave_to_start.inc
|
||||||
set default_master_connection = 'MASTER 2.2';
|
set default_master_connection = 'MASTER 2.2';
|
||||||
include/wait_for_slave_to_start.inc
|
include/wait_for_slave_to_start.inc
|
||||||
set default_master_connection = '';
|
set default_master_connection = '';
|
||||||
show all slaves status;
|
show all slaves status;
|
||||||
Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos
|
Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos
|
||||||
Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 <read_master_log_pos> relay.000004 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 1 No conservative 0 1073741824 6 0 60.000
|
Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 <read_master_log_pos> relay.000004 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 1 No conservative 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 1073741824 6 0 60.000
|
||||||
MASTER 2.2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> relay-master@00202@002e2.000004 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space2> None 0 No 0 No 0 0 2 No conservative 0 1073741824 6 0 60.000
|
MASTER 2.2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> relay-master@00202@002e2.000004 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space2> None 0 No 0 No 0 0 2 No conservative 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 1073741824 6 0 60.000
|
||||||
#
|
#
|
||||||
# List of files matching '*info*' pattern
|
# List of files matching '*info*' pattern
|
||||||
# after slave server restart
|
# after slave server restart
|
||||||
|
@ -13,15 +13,15 @@ insert into t1 values (1),(2);
|
|||||||
connection slave;
|
connection slave;
|
||||||
stop slave 'master1';
|
stop slave 'master1';
|
||||||
show slave 'master1' status;
|
show slave 'master1' status;
|
||||||
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode
|
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State
|
||||||
127.0.0.1 root MYPORT_1 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-master1.000002 <relay_log_pos> master-bin.000001 No No 0 0 <read_master_log_pos> <relay_log_space> None 0 No NULL No 0 0 1 No conservative
|
127.0.0.1 root MYPORT_1 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-master1.000002 <relay_log_pos> master-bin.000001 No No 0 0 <read_master_log_pos> <relay_log_space> None 0 No NULL No 0 0 1 No conservative 0 NULL
|
||||||
mysqld-relay-bin-master1.000001
|
mysqld-relay-bin-master1.000001
|
||||||
mysqld-relay-bin-master1.000002
|
mysqld-relay-bin-master1.000002
|
||||||
mysqld-relay-bin-master1.index
|
mysqld-relay-bin-master1.index
|
||||||
reset slave 'master1';
|
reset slave 'master1';
|
||||||
show slave 'master1' status;
|
show slave 'master1' status;
|
||||||
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode
|
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State
|
||||||
127.0.0.1 root MYPORT_1 60 4 <relay_log_pos> No No 0 0 0 <relay_log_space> None 0 No NULL No 0 0 1 No conservative
|
127.0.0.1 root MYPORT_1 60 4 <relay_log_pos> No No 0 0 0 <relay_log_space> None 0 No NULL No 0 0 1 No conservative 0 NULL
|
||||||
reset slave 'master1' all;
|
reset slave 'master1' all;
|
||||||
show slave 'master1' status;
|
show slave 'master1' status;
|
||||||
ERROR HY000: There is no master connection 'master1'
|
ERROR HY000: There is no master connection 'master1'
|
||||||
|
@ -18,9 +18,9 @@ connection slave;
|
|||||||
connection master2;
|
connection master2;
|
||||||
connection slave;
|
connection slave;
|
||||||
show all slaves status;
|
show all slaves status;
|
||||||
Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos
|
Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos
|
||||||
slave1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-slave1.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 1 No conservative 0 1073741824 7 0 60.000
|
slave1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-slave1.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 1 No conservative 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 1073741824 7 0 60.000
|
||||||
slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-slave2.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 2 No conservative 0 1073741824 7 0 60.000
|
slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-slave2.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 2 No conservative 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 1073741824 7 0 60.000
|
||||||
start all slaves;
|
start all slaves;
|
||||||
stop slave 'slave1';
|
stop slave 'slave1';
|
||||||
show slave 'slave1' status;
|
show slave 'slave1' status;
|
||||||
@ -71,21 +71,24 @@ Gtid_IO_Pos
|
|||||||
Replicate_Do_Domain_Ids
|
Replicate_Do_Domain_Ids
|
||||||
Replicate_Ignore_Domain_Ids
|
Replicate_Ignore_Domain_Ids
|
||||||
Parallel_Mode conservative
|
Parallel_Mode conservative
|
||||||
|
SQL_Delay 0
|
||||||
|
SQL_Remaining_Delay NULL
|
||||||
|
Slave_SQL_Running_State
|
||||||
reset slave 'slave1';
|
reset slave 'slave1';
|
||||||
show all slaves status;
|
show all slaves status;
|
||||||
Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos
|
Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos
|
||||||
slave1 127.0.0.1 root MYPORT_1 60 4 <relay_log_pos> No No 0 0 0 <relay_log_space1> None 0 No NULL No 0 0 1 No conservative 0 1073741824 7 0 60.000
|
slave1 127.0.0.1 root MYPORT_1 60 4 <relay_log_pos> No No 0 0 0 <relay_log_space1> None 0 No NULL No 0 0 1 No conservative 0 NULL 0 1073741824 7 0 60.000
|
||||||
slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-slave2.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 2 No conservative 0 1073741824 7 0 60.000
|
slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-slave2.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 2 No conservative 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 1073741824 7 0 60.000
|
||||||
reset slave 'slave1' all;
|
reset slave 'slave1' all;
|
||||||
show all slaves status;
|
show all slaves status;
|
||||||
Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos
|
Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos
|
||||||
slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-slave2.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 2 No conservative 0 1073741824 7 0 60.000
|
slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-slave2.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 2 No conservative 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 1073741824 7 0 60.000
|
||||||
stop all slaves;
|
stop all slaves;
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1938 SLAVE 'slave2' stopped
|
Note 1938 SLAVE 'slave2' stopped
|
||||||
show all slaves status;
|
show all slaves status;
|
||||||
Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos
|
Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos
|
||||||
slave2 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-slave2.000002 <relay_log_pos> master-bin.000001 No No 0 0 <read_master_log_pos> <relay_log_space1> None 0 No NULL No 0 0 2 No conservative 0 1073741824 7 0 60.000
|
slave2 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-slave2.000002 <relay_log_pos> master-bin.000001 No No 0 0 <read_master_log_pos> <relay_log_space1> None 0 No NULL No 0 0 2 No conservative 0 NULL 0 1073741824 7 0 60.000
|
||||||
stop all slaves;
|
stop all slaves;
|
||||||
include/reset_master_slave.inc
|
include/reset_master_slave.inc
|
||||||
disconnect slave;
|
disconnect slave;
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
include/master-slave.inc
|
include/master-slave.inc
|
||||||
[connection master]
|
[connection master]
|
||||||
show slave status;
|
show slave status;
|
||||||
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode
|
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State
|
||||||
show slave '' status;
|
show slave '' status;
|
||||||
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode
|
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State
|
||||||
show all slaves status;
|
show all slaves status;
|
||||||
Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos
|
Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed 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 Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos
|
||||||
#
|
#
|
||||||
# Check error handling
|
# Check error handling
|
||||||
#
|
#
|
||||||
|
17
mysql-test/suite/rpl/r/rpl_delayed_slave,parallel.rdiff
Normal file
17
mysql-test/suite/rpl/r/rpl_delayed_slave,parallel.rdiff
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
--- mysql-test/suite/rpl/r/rpl_delayed_slave.result 2016-10-14 21:14:02.338075590 +0200
|
||||||
|
+++ mysql-test/suite/rpl/r/rpl_delayed_slave,parallel.reject 2016-10-14 21:17:51.296986686 +0200
|
||||||
|
@@ -45,7 +45,6 @@
|
||||||
|
# wait for first query to execute
|
||||||
|
# sleep 1*T
|
||||||
|
# Asserted this: Second query executed
|
||||||
|
-# Asserted this: Status should be executing third query (i.e., 'User sleep')
|
||||||
|
# sleep 2*T
|
||||||
|
# Asserted this: Third query executed
|
||||||
|
# Asserted this: Status should be 'Has read all relay log...'
|
||||||
|
@@ -167,5 +166,5 @@
|
||||||
|
conservative
|
||||||
|
SELECT @@GLOBAL.slave_parallel_threads;
|
||||||
|
@@GLOBAL.slave_parallel_threads
|
||||||
|
-0
|
||||||
|
+10
|
||||||
|
include/rpl_end.inc
|
192
mysql-test/suite/rpl/r/rpl_delayed_slave.result
Normal file
192
mysql-test/suite/rpl/r/rpl_delayed_slave.result
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
include/master-slave.inc
|
||||||
|
[connection master]
|
||||||
|
call mtr.add_suppression("Unsafe statement written to the binary log using statement format");
|
||||||
|
connection slave;
|
||||||
|
call mtr.add_suppression("Unsafe statement written to the binary log using statement format");
|
||||||
|
connection master;
|
||||||
|
[on master]
|
||||||
|
CREATE TABLE t1 (a VARCHAR(100), b INT);
|
||||||
|
INSERT INTO t1 VALUES ("zero", 0);
|
||||||
|
==== Normal setup ====
|
||||||
|
[on slave]
|
||||||
|
connection slave;
|
||||||
|
include/stop_slave.inc
|
||||||
|
# CHANGE MASTER TO MASTER_DELAY = 2*T
|
||||||
|
include/start_slave.inc
|
||||||
|
# Asserted this: SHOW SLAVE STATUS should return the same delay that we set with CHANGE MASTER
|
||||||
|
[on master]
|
||||||
|
connection master;
|
||||||
|
INSERT INTO t1 VALUES ('normal setup', 1);
|
||||||
|
connection master;
|
||||||
|
[on slave]
|
||||||
|
include/sync_slave_io_with_master.inc
|
||||||
|
# sleep 1*T
|
||||||
|
# Asserted this: Query 1 should not be executed
|
||||||
|
# Asserted this: Status should be 'Waiting until MASTER_DELAY...'
|
||||||
|
# sleep 1*T
|
||||||
|
# sync with master (with timeout 1*T)
|
||||||
|
include/wait_for_slave_param.inc [Relay_Master_Log_File]
|
||||||
|
include/wait_for_slave_param.inc [Exec_Master_Log_Pos]
|
||||||
|
# Asserted this: Query 1 should be executed
|
||||||
|
# Asserted this: Status should be 'Has read all relay log...'
|
||||||
|
include/check_slave_is_running.inc
|
||||||
|
==== Slave lags "naturally" after master ====
|
||||||
|
[on master]
|
||||||
|
connection master;
|
||||||
|
# CREATE FUNCTION delay_on_slave(time_units INT) RETURNS INT BEGIN IF @@GLOBAL.server_id = 2 THEN RETURN SLEEP(time_units * T); ELSE RETURN 0; END IF; END
|
||||||
|
INSERT INTO t1 SELECT delay_on_slave(3), 2;
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave
|
||||||
|
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave
|
||||||
|
INSERT INTO t1 VALUES ('slave is already lagging: this statement should execute immediately', 3);
|
||||||
|
INSERT INTO t1 SELECT delay_on_slave(2), 4;
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave
|
||||||
|
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave
|
||||||
|
[on slave]
|
||||||
|
include/sync_slave_io_with_master.inc
|
||||||
|
# sleep 1*T
|
||||||
|
# Asserted this: No query executed
|
||||||
|
# Asserted this: Status should be 'Waiting until MASTER_DELAY...'
|
||||||
|
# wait for first query to execute
|
||||||
|
# sleep 1*T
|
||||||
|
# Asserted this: Second query executed
|
||||||
|
# Asserted this: Status should be executing third query (i.e., 'User sleep')
|
||||||
|
# sleep 2*T
|
||||||
|
# Asserted this: Third query executed
|
||||||
|
# Asserted this: Status should be 'Has read all relay log...'
|
||||||
|
==== Seconds_Behind_Master ====
|
||||||
|
# Bring slave to sync.
|
||||||
|
include/stop_slave.inc
|
||||||
|
CHANGE MASTER TO MASTER_DELAY = 0;
|
||||||
|
include/start_slave.inc
|
||||||
|
connection master;
|
||||||
|
INSERT INTO t1 VALUES ('Syncing slave', 5);
|
||||||
|
connection slave;
|
||||||
|
include/stop_slave.inc
|
||||||
|
# CHANGE MASTER TO MASTER_DELAY = 2*T
|
||||||
|
include/start_slave.inc
|
||||||
|
connection master;
|
||||||
|
INSERT INTO t1 VALUES (delay_on_slave(1), 6);
|
||||||
|
Warnings:
|
||||||
|
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave
|
||||||
|
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave
|
||||||
|
connection slave;
|
||||||
|
# sleep 1*T
|
||||||
|
# Asserted this: Seconds_Behind_Master should be between 0 and the 2*T
|
||||||
|
# sleep 1*T
|
||||||
|
# Asserted this: Seconds_Behind_Master should be at least 2*T
|
||||||
|
==== STOP SLAVE / START SLAVE + DML ====
|
||||||
|
include/stop_slave.inc
|
||||||
|
# CHANGE MASTER TO MASTER_DELAY = 3*T
|
||||||
|
include/start_slave.inc
|
||||||
|
[on master]
|
||||||
|
connection master;
|
||||||
|
INSERT INTO t1 VALUES ('stop slave and start slave: DML', 7);
|
||||||
|
[on slave]
|
||||||
|
connection slave;
|
||||||
|
# sleep 1*T
|
||||||
|
include/stop_slave.inc
|
||||||
|
# Asserted this: STOP SLAVE should finish quickly, not wait for the ongoing sleep to finish
|
||||||
|
# Asserted this: SQL thread position should not increase after STOP SLAVE
|
||||||
|
# Asserted this: Query should not be executed after STOP SLAVE
|
||||||
|
# Asserted this: Status should be '' after STOP SLAVE
|
||||||
|
include/start_slave.inc
|
||||||
|
# Asserted this: START SLAVE should finish quickly
|
||||||
|
connection master;
|
||||||
|
[on slave]
|
||||||
|
include/sync_slave_io_with_master.inc
|
||||||
|
# sleep 1*T
|
||||||
|
# Asserted this: Query 7 should not be executed
|
||||||
|
# Asserted this: Status should be 'Waiting until MASTER_DELAY...'
|
||||||
|
# sleep 1*T
|
||||||
|
# sync with master (with timeout 1*T)
|
||||||
|
include/wait_for_slave_param.inc [Relay_Master_Log_File]
|
||||||
|
include/wait_for_slave_param.inc [Exec_Master_Log_Pos]
|
||||||
|
# Asserted this: Query 7 should be executed
|
||||||
|
# Asserted this: Status should be 'Has read all relay log...'
|
||||||
|
include/check_slave_is_running.inc
|
||||||
|
==== STOP SLAVE / START SLAVE + DDL ====
|
||||||
|
This verifies BUG#56442
|
||||||
|
[on master]
|
||||||
|
connection master;
|
||||||
|
CREATE TABLE t_check_dml_not_executed_prematurely (a INT);
|
||||||
|
include/save_master_pos.inc
|
||||||
|
[on slave]
|
||||||
|
connection slave;
|
||||||
|
# sleep 1*T
|
||||||
|
include/stop_slave.inc
|
||||||
|
# Asserted this: STOP SLAVE should finish quickly, not wait for the ongoing sleep to finish
|
||||||
|
# Asserted this: SQL thread position should not increase after STOP SLAVE
|
||||||
|
# Asserted this: Query should not be executed after STOP SLAVE
|
||||||
|
# Asserted this: Status should be '' after STOP SLAVE
|
||||||
|
include/start_slave.inc
|
||||||
|
# Asserted this: START SLAVE should finish quickly
|
||||||
|
# sleep 1*T
|
||||||
|
# Asserted this: DDL Query should not be executed after START SLAVE
|
||||||
|
# Asserted this: Status should be 'Waiting until MASTER_DELAY...'
|
||||||
|
# sleep 1*T
|
||||||
|
# sync with master (with timeout 1*T)
|
||||||
|
include/wait_for_slave_param.inc [Relay_Master_Log_File]
|
||||||
|
include/wait_for_slave_param.inc [Exec_Master_Log_Pos]
|
||||||
|
# Asserted this: DDL Query should be executed
|
||||||
|
# Asserted this: Status should be 'Has read all relay log...'
|
||||||
|
include/check_slave_is_running.inc
|
||||||
|
==== Change back to no delay ====
|
||||||
|
[on slave]
|
||||||
|
connection slave;
|
||||||
|
include/stop_slave.inc
|
||||||
|
CHANGE MASTER TO MASTER_DELAY = 0;
|
||||||
|
# Asserted this: Delay should be 0 when we set it to 0
|
||||||
|
include/start_slave.inc
|
||||||
|
[on master]
|
||||||
|
connection master;
|
||||||
|
INSERT INTO t1 VALUES ('change back to no delay', 8);
|
||||||
|
[on slave]
|
||||||
|
include/sync_slave_io_with_master.inc
|
||||||
|
# sleep 1*T
|
||||||
|
# Asserted this: Query should be executed
|
||||||
|
# Asserted this: Status should be 'Slave has read all relay log...'
|
||||||
|
==== Reset delay with RESET SLAVE ====
|
||||||
|
include/stop_slave.inc
|
||||||
|
CHANGE MASTER TO MASTER_DELAY = 71;
|
||||||
|
include/start_slave.inc
|
||||||
|
# Asserted this: Delay should be 71 when we set it to 71
|
||||||
|
include/stop_slave.inc
|
||||||
|
RESET SLAVE;
|
||||||
|
[on master]
|
||||||
|
connection master;
|
||||||
|
RESET MASTER;
|
||||||
|
[on slave]
|
||||||
|
connection slave;
|
||||||
|
include/start_slave.inc
|
||||||
|
# Asserted this: Delay should be 0 after RESET SLAVE
|
||||||
|
==== Set an invalid value for the delay ====
|
||||||
|
include/stop_slave.inc
|
||||||
|
# Expect error for setting negative delay
|
||||||
|
CHANGE MASTER TO MASTER_DELAY = -1;
|
||||||
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '-1' at line 1
|
||||||
|
# Expect that it's ok to set delay of 2^31-1
|
||||||
|
CHANGE MASTER TO MASTER_DELAY = 2147483647;
|
||||||
|
# Expect error for setting delay between 2^31 and 2^32-1
|
||||||
|
CHANGE MASTER TO MASTER_DELAY = 2147483648;
|
||||||
|
ERROR HY000: The requested value 2147483648 for the master delay exceeds the maximum 2147483647
|
||||||
|
# Expect error for setting delay to nonsense
|
||||||
|
CHANGE MASTER TO MASTER_DELAY = blah;
|
||||||
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'blah' at line 1
|
||||||
|
CHANGE MASTER TO MASTER_DELAY = 0;
|
||||||
|
include/start_slave.inc
|
||||||
|
==== Clean up ====
|
||||||
|
[on master]
|
||||||
|
connection master;
|
||||||
|
DROP TABLE t1, t_check_dml_not_executed_prematurely;
|
||||||
|
DROP FUNCTION delay_on_slave;
|
||||||
|
[on slave]
|
||||||
|
connection slave;
|
||||||
|
SELECT @@GLOBAL.slave_parallel_mode;
|
||||||
|
@@GLOBAL.slave_parallel_mode
|
||||||
|
conservative
|
||||||
|
SELECT @@GLOBAL.slave_parallel_threads;
|
||||||
|
@@GLOBAL.slave_parallel_threads
|
||||||
|
0
|
||||||
|
include/rpl_end.inc
|
58
mysql-test/suite/rpl/r/rpl_delayed_slave2.result
Normal file
58
mysql-test/suite/rpl/r/rpl_delayed_slave2.result
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
include/master-slave.inc
|
||||||
|
[connection master]
|
||||||
|
connection master;
|
||||||
|
ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(100));
|
||||||
|
INSERT INTO t1 VALUES (1, "a");
|
||||||
|
connection slave;
|
||||||
|
include/stop_slave.inc
|
||||||
|
CHANGE MASTER TO master_use_gtid=slave_pos;
|
||||||
|
SET @old_mode= @@GLOBAL.slave_parallel_mode;
|
||||||
|
SET GLOBAL slave_parallel_mode=optimistic;
|
||||||
|
SET @old_threads= @@GLOBAL.slave_parallel_threads;
|
||||||
|
SET GLOBAL slave_parallel_threads=10;
|
||||||
|
connection master;
|
||||||
|
INSERT INTO t1 VALUES (2, "b");
|
||||||
|
INSERT INTO t1 VALUES (3, "b");
|
||||||
|
INSERT INTO t1 VALUES (4, "b");
|
||||||
|
SET timestamp= @@timestamp + 24*60*60;
|
||||||
|
INSERT INTO t1 VALUES (5, "c");
|
||||||
|
INSERT INTO t1 VALUES (6, "c");
|
||||||
|
SET timestamp= 0;
|
||||||
|
include/save_master_gtid.inc
|
||||||
|
connection slave;
|
||||||
|
CHANGE MASTER TO master_delay=1;
|
||||||
|
include/start_slave.inc
|
||||||
|
SELECT MASTER_GTID_WAIT('GTID1');
|
||||||
|
MASTER_GTID_WAIT('GTID1')
|
||||||
|
0
|
||||||
|
SELECT MASTER_GTID_WAIT('GTID2', 2);
|
||||||
|
MASTER_GTID_WAIT('GTID2', 2)
|
||||||
|
-1
|
||||||
|
include/stop_slave.inc
|
||||||
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
a b
|
||||||
|
1 a
|
||||||
|
2 b
|
||||||
|
3 b
|
||||||
|
4 b
|
||||||
|
CHANGE MASTER TO master_delay=0;
|
||||||
|
include/start_slave.inc
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
a b
|
||||||
|
1 a
|
||||||
|
2 b
|
||||||
|
3 b
|
||||||
|
4 b
|
||||||
|
5 c
|
||||||
|
6 c
|
||||||
|
connection slave;
|
||||||
|
include/stop_slave.inc
|
||||||
|
CHANGE MASTER TO master_use_gtid=no, master_delay=0;
|
||||||
|
SET GLOBAL slave_parallel_mode=@old_mode;
|
||||||
|
SET GLOBAL slave_parallel_threads=@old_threads;
|
||||||
|
include/start_slave.inc
|
||||||
|
connection master;
|
||||||
|
DROP TABLE t1;
|
||||||
|
include/rpl_end.inc
|
5
mysql-test/suite/rpl/t/rpl_delayed_slave.combinations
Normal file
5
mysql-test/suite/rpl/t/rpl_delayed_slave.combinations
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[nonparallel]
|
||||||
|
|
||||||
|
[parallel]
|
||||||
|
--slave-parallel-mode=conservative
|
||||||
|
--slave-parallel-threads=10
|
424
mysql-test/suite/rpl/t/rpl_delayed_slave.test
Normal file
424
mysql-test/suite/rpl/t/rpl_delayed_slave.test
Normal file
@ -0,0 +1,424 @@
|
|||||||
|
# ==== Purpose ====
|
||||||
|
#
|
||||||
|
# Test the time-delayed replication feature, i.e.,
|
||||||
|
# CHANGE MASTER TO MASTER_DELAY=X:
|
||||||
|
#
|
||||||
|
# - Verify that slave has executed the events after but not before the
|
||||||
|
# delay timeout.
|
||||||
|
#
|
||||||
|
# - Verify that delay is correct when slave is already lagging
|
||||||
|
# due to slow queries.
|
||||||
|
#
|
||||||
|
# - Verify that Seconds_Behind_Master is greater than or equal to the
|
||||||
|
# delay if the slave still has unprocessed events in the relay log
|
||||||
|
# and more time than the delay has elapsed since the last event was
|
||||||
|
# executed on the master.
|
||||||
|
#
|
||||||
|
# - Verify that STOP SLAVE works instantly even during a delay, and
|
||||||
|
# that it does not cause the waited-for event to be executed too
|
||||||
|
# early on slave.
|
||||||
|
#
|
||||||
|
# - Verify that changing back to no delay works.
|
||||||
|
#
|
||||||
|
# - Verify that RESET SLAVE sets the delay to 0.
|
||||||
|
#
|
||||||
|
# - Verify that setting a bad value for the delay gives an error.
|
||||||
|
#
|
||||||
|
# ==== Implementation ====
|
||||||
|
#
|
||||||
|
# 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 that a query has been executed after this
|
||||||
|
# time, we wait 10 seconds more.
|
||||||
|
#
|
||||||
|
# To simulate that the slave lags due to slow queries, we invoke a
|
||||||
|
# stored function that executes SLEEP if @@gloval.server_id==2. This
|
||||||
|
# requires that we run with binlog_format=STATEMENT.
|
||||||
|
#
|
||||||
|
# ==== 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
|
||||||
|
# BUG#56442: Slave executes delayed statements when STOP SLAVE is issued
|
||||||
|
#
|
||||||
|
# ==== Issues with this Test Case ====
|
||||||
|
#
|
||||||
|
# The test is inherently timing-sensitive (i.e., contains races) and
|
||||||
|
# is likely to fail sporadically on a loaded host.
|
||||||
|
#
|
||||||
|
# The test takes a long time; it sleeps for around 20*10 seconds.
|
||||||
|
|
||||||
|
--source include/big_test.inc
|
||||||
|
--source include/not_valgrind.inc
|
||||||
|
--source include/master-slave.inc
|
||||||
|
# Needed so that sleeps get executed in the slave SQL thread.
|
||||||
|
--source include/have_binlog_format_statement.inc
|
||||||
|
|
||||||
|
|
||||||
|
call mtr.add_suppression("Unsafe statement written to the binary log using statement format");
|
||||||
|
--connection slave
|
||||||
|
call mtr.add_suppression("Unsafe statement written to the binary log using statement format");
|
||||||
|
--connection master
|
||||||
|
|
||||||
|
|
||||||
|
# We assume that any simple operation takes zero time, with an error
|
||||||
|
# margin of $time1 seconds. Hence, if we run with a delay of $time2
|
||||||
|
# seconds, we expect that:
|
||||||
|
# - If we execute a query on master and wait $time1 seconds, then the
|
||||||
|
# query has been copied to slave but not yet executed.
|
||||||
|
# - If we execute a query on master and wait $time3 seconds, then the
|
||||||
|
# query has been executed.
|
||||||
|
--let $time1= 10
|
||||||
|
if (`SELECT '$max_query_execution_time' > 0`) {
|
||||||
|
--let $time1= $max_query_execution_time
|
||||||
|
}
|
||||||
|
--let $time2= `SELECT 2 * $time1`
|
||||||
|
--let $time3= `SELECT 3 * $time1`
|
||||||
|
|
||||||
|
|
||||||
|
--echo [on master]
|
||||||
|
CREATE TABLE t1 (a VARCHAR(100), b INT);
|
||||||
|
INSERT INTO t1 VALUES ("zero", 0);
|
||||||
|
|
||||||
|
|
||||||
|
--echo ==== Normal setup ====
|
||||||
|
|
||||||
|
--echo [on slave]
|
||||||
|
--sync_slave_with_master
|
||||||
|
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
|
||||||
|
--echo # CHANGE MASTER TO MASTER_DELAY = 2*T
|
||||||
|
--disable_query_log
|
||||||
|
eval CHANGE MASTER TO MASTER_DELAY = $time2;
|
||||||
|
--enable_query_log
|
||||||
|
|
||||||
|
--source include/start_slave.inc
|
||||||
|
|
||||||
|
--let $assert_text= SHOW SLAVE STATUS should return the same delay that we set with CHANGE MASTER
|
||||||
|
--let $assert_cond= [SHOW SLAVE STATUS, SQL_Delay, 1] = $time2
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--echo [on master]
|
||||||
|
--connection master
|
||||||
|
INSERT INTO t1 VALUES ('normal setup', 1);
|
||||||
|
|
||||||
|
--let $query_number= 1
|
||||||
|
--source extra/rpl_tests/delayed_slave_wait_on_query.inc
|
||||||
|
|
||||||
|
|
||||||
|
--echo ==== Slave lags "naturally" after master ====
|
||||||
|
|
||||||
|
--echo [on master]
|
||||||
|
--connection master
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
--echo # CREATE FUNCTION delay_on_slave(time_units INT) RETURNS INT BEGIN IF @@GLOBAL.server_id = 2 THEN RETURN SLEEP(time_units * T); ELSE RETURN 0; END IF; END
|
||||||
|
--eval CREATE FUNCTION delay_on_slave(time_units INT) RETURNS INT BEGIN IF @@GLOBAL.server_id = 2 THEN RETURN SLEEP(time_units * $time1); ELSE RETURN 0; END IF; END
|
||||||
|
--enable_query_log
|
||||||
|
|
||||||
|
INSERT INTO t1 SELECT delay_on_slave(3), 2;
|
||||||
|
|
||||||
|
--save_master_pos
|
||||||
|
INSERT INTO t1 VALUES ('slave is already lagging: this statement should execute immediately', 3);
|
||||||
|
INSERT INTO t1 SELECT delay_on_slave(2), 4;
|
||||||
|
|
||||||
|
--echo [on slave]
|
||||||
|
--source include/sync_slave_io_with_master.inc
|
||||||
|
--echo # sleep 1*T
|
||||||
|
--sleep $time1
|
||||||
|
|
||||||
|
--let $assert_text= No query executed
|
||||||
|
--let $assert_cond= MAX(b) = 1 FROM t1
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--let $assert_text= Status should be 'Waiting until MASTER_DELAY...'
|
||||||
|
--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" LIKE "Waiting until MASTER_DELAY%"
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--echo # wait for first query to execute
|
||||||
|
--sync_with_master
|
||||||
|
|
||||||
|
--echo # sleep 1*T
|
||||||
|
--sleep $time1
|
||||||
|
|
||||||
|
--let $assert_text= Second query executed
|
||||||
|
--let $assert_cond= MAX(b) = 3 FROM t1
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
let $parallel= `SELECT @@GLOBAL.slave_parallel_threads`;
|
||||||
|
if (!$parallel)
|
||||||
|
{
|
||||||
|
let $assert_text= Status should be executing third query (i.e., 'User sleep');
|
||||||
|
let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" = "User sleep";
|
||||||
|
source include/rpl_assert.inc;
|
||||||
|
}
|
||||||
|
|
||||||
|
--echo # sleep 2*T
|
||||||
|
--sleep $time2
|
||||||
|
|
||||||
|
--let $assert_text= Third query executed
|
||||||
|
--let $assert_cond= MAX(b) = 4 FROM t1
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--let $assert_text= Status should be 'Has read all relay log...'
|
||||||
|
--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" LIKE "Slave has read all relay log%"
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
|
||||||
|
--echo ==== Seconds_Behind_Master ====
|
||||||
|
|
||||||
|
--echo # Bring slave to sync.
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
CHANGE MASTER TO MASTER_DELAY = 0;
|
||||||
|
--source include/start_slave.inc
|
||||||
|
|
||||||
|
--connection master
|
||||||
|
INSERT INTO t1 VALUES ('Syncing slave', 5);
|
||||||
|
--sync_slave_with_master
|
||||||
|
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
--echo # CHANGE MASTER TO MASTER_DELAY = 2*T
|
||||||
|
--disable_query_log
|
||||||
|
eval CHANGE MASTER TO MASTER_DELAY = $time2;
|
||||||
|
--enable_query_log
|
||||||
|
--source include/start_slave.inc
|
||||||
|
|
||||||
|
--connection master
|
||||||
|
INSERT INTO t1 VALUES (delay_on_slave(1), 6);
|
||||||
|
--save_master_pos
|
||||||
|
--connection slave
|
||||||
|
|
||||||
|
--echo # sleep 1*T
|
||||||
|
--sleep $time1
|
||||||
|
|
||||||
|
--let $assert_cond= [SHOW SLAVE STATUS, Seconds_Behind_Master, 1] >= 0 AND <1> < $time2
|
||||||
|
--let $assert_text= Seconds_Behind_Master should be between 0 and the 2*T
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--echo # sleep 1*T
|
||||||
|
--sleep $time1
|
||||||
|
|
||||||
|
--let $assert_cond= [SHOW SLAVE STATUS, Seconds_Behind_Master, 1] >= $time2
|
||||||
|
--let $assert_text= Seconds_Behind_Master should be at least 2*T
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--sync_with_master
|
||||||
|
|
||||||
|
|
||||||
|
--echo ==== STOP SLAVE / START SLAVE + DML ====
|
||||||
|
|
||||||
|
# Set up a longer delay.
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
|
||||||
|
--echo # CHANGE MASTER TO MASTER_DELAY = 3*T
|
||||||
|
--disable_query_log
|
||||||
|
eval CHANGE MASTER TO MASTER_DELAY = $time3;
|
||||||
|
--enable_query_log
|
||||||
|
|
||||||
|
--source include/start_slave.inc
|
||||||
|
|
||||||
|
--echo [on master]
|
||||||
|
--connection master
|
||||||
|
INSERT INTO t1 VALUES ('stop slave and start slave: DML', 7);
|
||||||
|
|
||||||
|
--echo [on slave]
|
||||||
|
--connection slave
|
||||||
|
--echo # sleep 1*T
|
||||||
|
--sleep $time1
|
||||||
|
--let $timestamp_before_stop= `SELECT UNIX_TIMESTAMP()`
|
||||||
|
--let $relay_log_pos_before_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1)
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
|
||||||
|
--let $assert_text= STOP SLAVE should finish quickly, not wait for the ongoing sleep to finish
|
||||||
|
--let $assert_cond= UNIX_TIMESTAMP() - $timestamp_before_stop < $time1
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--let $assert_text= SQL thread position should not increase after STOP SLAVE
|
||||||
|
--let $assert_cond= [SHOW SLAVE STATUS, Relay_Log_Pos, 1] = $relay_log_pos_before_stop
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--let $assert_text= Query should not be executed after STOP SLAVE
|
||||||
|
--let $assert_cond= MAX(b) = 6 FROM t1
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--let $assert_text= Status should be '' after STOP SLAVE
|
||||||
|
--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" = ""
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--source include/start_slave.inc
|
||||||
|
|
||||||
|
--let $assert_text= START SLAVE should finish quickly
|
||||||
|
--let $assert_cond= UNIX_TIMESTAMP() - $timestamp_before_stop < $time1
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--let $query_number= 7
|
||||||
|
--source extra/rpl_tests/delayed_slave_wait_on_query.inc
|
||||||
|
|
||||||
|
|
||||||
|
--echo ==== STOP SLAVE / START SLAVE + DDL ====
|
||||||
|
|
||||||
|
--echo This verifies BUG#56442
|
||||||
|
|
||||||
|
--echo [on master]
|
||||||
|
--connection master
|
||||||
|
CREATE TABLE t_check_dml_not_executed_prematurely (a INT);
|
||||||
|
--source include/save_master_pos.inc
|
||||||
|
|
||||||
|
--echo [on slave]
|
||||||
|
--connection slave
|
||||||
|
--echo # sleep 1*T
|
||||||
|
--sleep $time1
|
||||||
|
|
||||||
|
--let $timestamp_before_stop= `SELECT UNIX_TIMESTAMP()`
|
||||||
|
--let $relay_log_pos_before_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1)
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
|
||||||
|
--let $assert_text= STOP SLAVE should finish quickly, not wait for the ongoing sleep to finish
|
||||||
|
--let $assert_cond= UNIX_TIMESTAMP() - $timestamp_before_stop < $time1
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--let $assert_text= SQL thread position should not increase after STOP SLAVE
|
||||||
|
--let $assert_cond= [SHOW SLAVE STATUS, Relay_Log_Pos, 1] = $relay_log_pos_before_stop
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--let $assert_text= Query should not be executed after STOP SLAVE
|
||||||
|
--let $assert_cond= COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = "t_check_dml_not_executed_prematurely"
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--let $assert_text= Status should be '' after STOP SLAVE
|
||||||
|
--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" = ""
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--source include/start_slave.inc
|
||||||
|
|
||||||
|
--let $assert_text= START SLAVE should finish quickly
|
||||||
|
--let $assert_cond= UNIX_TIMESTAMP() - $timestamp_before_stop < $time1
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--echo # sleep 1*T
|
||||||
|
--sleep $time1
|
||||||
|
|
||||||
|
--let $assert_text= DDL Query should not be executed after START SLAVE
|
||||||
|
--let $assert_cond= COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = "t_check_dml_not_executed_prematurely"
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--let $assert_text= Status should be 'Waiting until MASTER_DELAY...'
|
||||||
|
--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" LIKE "Waiting until MASTER_DELAY%"
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--echo # sleep 1*T
|
||||||
|
--sleep $time1
|
||||||
|
|
||||||
|
--echo # sync with master (with timeout 1*T)
|
||||||
|
--source include/sync_with_master.inc
|
||||||
|
|
||||||
|
--let $assert_text= DDL Query should be executed
|
||||||
|
--let $assert_cond= COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = "t_check_dml_not_executed_prematurely"
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--let $assert_text= Status should be 'Has read all relay log...'
|
||||||
|
--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" LIKE "Slave has read all relay log%"
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--source include/check_slave_is_running.inc
|
||||||
|
|
||||||
|
|
||||||
|
--echo ==== Change back to no delay ====
|
||||||
|
|
||||||
|
--echo [on slave]
|
||||||
|
--connection slave
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
CHANGE MASTER TO MASTER_DELAY = 0;
|
||||||
|
|
||||||
|
--let $assert_text= Delay should be 0 when we set it to 0
|
||||||
|
--let $assert_cond= [SHOW SLAVE STATUS, SQL_Delay, 1] = 0
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--source include/start_slave.inc
|
||||||
|
|
||||||
|
--echo [on master]
|
||||||
|
--connection master
|
||||||
|
INSERT INTO t1 VALUES ('change back to no delay', 8);
|
||||||
|
|
||||||
|
--echo [on slave]
|
||||||
|
--source include/sync_slave_io_with_master.inc
|
||||||
|
--echo # sleep 1*T
|
||||||
|
--sleep $time1
|
||||||
|
|
||||||
|
--let $assert_text= Query should be executed
|
||||||
|
--let $assert_cond= MAX(b) = 8 FROM t1
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--let $assert_text= Status should be 'Slave has read all relay log...'
|
||||||
|
--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" Like "Slave has read all relay log%"
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
|
||||||
|
--echo ==== Reset delay with RESET SLAVE ====
|
||||||
|
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
CHANGE MASTER TO MASTER_DELAY = 71;
|
||||||
|
--source include/start_slave.inc
|
||||||
|
|
||||||
|
--let $assert_text= Delay should be 71 when we set it to 71
|
||||||
|
--let $assert_cond= [SHOW SLAVE STATUS, SQL_Delay, 1] = 71
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
RESET SLAVE;
|
||||||
|
--echo [on master]
|
||||||
|
--connection master
|
||||||
|
RESET MASTER;
|
||||||
|
--echo [on slave]
|
||||||
|
--connection slave
|
||||||
|
--source include/start_slave.inc
|
||||||
|
|
||||||
|
--let $assert_text= Delay should be 0 after RESET SLAVE
|
||||||
|
--let $assert_cond= [SHOW SLAVE STATUS, SQL_Delay, 1] = 0
|
||||||
|
--source include/rpl_assert.inc
|
||||||
|
|
||||||
|
|
||||||
|
--echo ==== Set an invalid value for the delay ====
|
||||||
|
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
|
||||||
|
--echo # Expect error for setting negative delay
|
||||||
|
--error ER_PARSE_ERROR
|
||||||
|
CHANGE MASTER TO MASTER_DELAY = -1;
|
||||||
|
|
||||||
|
--echo # Expect that it's ok to set delay of 2^31-1
|
||||||
|
CHANGE MASTER TO MASTER_DELAY = 2147483647;
|
||||||
|
--echo # Expect error for setting delay between 2^31 and 2^32-1
|
||||||
|
--error ER_MASTER_DELAY_VALUE_OUT_OF_RANGE
|
||||||
|
CHANGE MASTER TO MASTER_DELAY = 2147483648;
|
||||||
|
|
||||||
|
--echo # Expect error for setting delay to nonsense
|
||||||
|
--error ER_PARSE_ERROR
|
||||||
|
CHANGE MASTER TO MASTER_DELAY = blah;
|
||||||
|
|
||||||
|
# todo: CHANGE MASTER TO MASTER_DELAY = 999999999999999999999999999
|
||||||
|
# should give error
|
||||||
|
|
||||||
|
CHANGE MASTER TO MASTER_DELAY = 0;
|
||||||
|
--source include/start_slave.inc
|
||||||
|
|
||||||
|
|
||||||
|
--echo ==== Clean up ====
|
||||||
|
|
||||||
|
--echo [on master]
|
||||||
|
--connection master
|
||||||
|
DROP TABLE t1, t_check_dml_not_executed_prematurely;
|
||||||
|
DROP FUNCTION delay_on_slave;
|
||||||
|
|
||||||
|
--echo [on slave]
|
||||||
|
--sync_slave_with_master
|
||||||
|
SELECT @@GLOBAL.slave_parallel_mode;
|
||||||
|
SELECT @@GLOBAL.slave_parallel_threads;
|
||||||
|
|
||||||
|
--source include/rpl_end.inc
|
65
mysql-test/suite/rpl/t/rpl_delayed_slave2.test
Normal file
65
mysql-test/suite/rpl/t/rpl_delayed_slave2.test
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
--source include/have_innodb.inc
|
||||||
|
--source include/master-slave.inc
|
||||||
|
|
||||||
|
# This test file tests delayed slave for parallel replication (and GTID).
|
||||||
|
# Uses a different approach from rpl_delayed_slave.test, setting @@timestamp
|
||||||
|
# to simulate events logged on master at different times.
|
||||||
|
|
||||||
|
--connection master
|
||||||
|
ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(100));
|
||||||
|
INSERT INTO t1 VALUES (1, "a");
|
||||||
|
--save_master_pos
|
||||||
|
|
||||||
|
--connection slave
|
||||||
|
--sync_with_master
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
CHANGE MASTER TO master_use_gtid=slave_pos;
|
||||||
|
SET @old_mode= @@GLOBAL.slave_parallel_mode;
|
||||||
|
SET GLOBAL slave_parallel_mode=optimistic;
|
||||||
|
SET @old_threads= @@GLOBAL.slave_parallel_threads;
|
||||||
|
SET GLOBAL slave_parallel_threads=10;
|
||||||
|
|
||||||
|
--connection master
|
||||||
|
INSERT INTO t1 VALUES (2, "b");
|
||||||
|
INSERT INTO t1 VALUES (3, "b");
|
||||||
|
INSERT INTO t1 VALUES (4, "b");
|
||||||
|
--let $gtid1= `SELECT @@gtid_binlog_pos`
|
||||||
|
# Simulate an event a days in the future, for delayed slave to wait on.
|
||||||
|
SET timestamp= @@timestamp + 24*60*60;
|
||||||
|
INSERT INTO t1 VALUES (5, "c");
|
||||||
|
INSERT INTO t1 VALUES (6, "c");
|
||||||
|
SET timestamp= 0;
|
||||||
|
--let $gtid2= `SELECT @@gtid_binlog_pos`
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
|
--connection slave
|
||||||
|
CHANGE MASTER TO master_delay=1;
|
||||||
|
--source include/start_slave.inc
|
||||||
|
--replace_result $gtid1 GTID1
|
||||||
|
# First sync halfways, to avoid timing-dependent test failures.
|
||||||
|
eval SELECT MASTER_GTID_WAIT('$gtid1');
|
||||||
|
# Try to sync up, should timeout because slave is waiting for one day.
|
||||||
|
--replace_result $gtid2 GTID2
|
||||||
|
eval SELECT MASTER_GTID_WAIT('$gtid2', 2);
|
||||||
|
|
||||||
|
# Check that we can stop slave while delaying.
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
CHANGE MASTER TO master_delay=0;
|
||||||
|
--source include/start_slave.inc
|
||||||
|
--source include/sync_with_master_gtid.inc
|
||||||
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
|
||||||
|
|
||||||
|
--connection slave
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
CHANGE MASTER TO master_use_gtid=no, master_delay=0;
|
||||||
|
SET GLOBAL slave_parallel_mode=@old_mode;
|
||||||
|
SET GLOBAL slave_parallel_threads=@old_threads;
|
||||||
|
--source include/start_slave.inc
|
||||||
|
|
||||||
|
--connection master
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--source include/rpl_end.inc
|
@ -343,6 +343,7 @@ static SYMBOL symbols[] = {
|
|||||||
{ "LOW_PRIORITY", SYM(LOW_PRIORITY)},
|
{ "LOW_PRIORITY", SYM(LOW_PRIORITY)},
|
||||||
{ "MASTER", SYM(MASTER_SYM)},
|
{ "MASTER", SYM(MASTER_SYM)},
|
||||||
{ "MASTER_CONNECT_RETRY", SYM(MASTER_CONNECT_RETRY_SYM)},
|
{ "MASTER_CONNECT_RETRY", SYM(MASTER_CONNECT_RETRY_SYM)},
|
||||||
|
{ "MASTER_DELAY", SYM(MASTER_DELAY_SYM)},
|
||||||
{ "MASTER_GTID_POS", SYM(MASTER_GTID_POS_SYM)},
|
{ "MASTER_GTID_POS", SYM(MASTER_GTID_POS_SYM)},
|
||||||
{ "MASTER_HOST", SYM(MASTER_HOST_SYM)},
|
{ "MASTER_HOST", SYM(MASTER_HOST_SYM)},
|
||||||
{ "MASTER_LOG_FILE", SYM(MASTER_LOG_FILE_SYM)},
|
{ "MASTER_LOG_FILE", SYM(MASTER_LOG_FILE_SYM)},
|
||||||
|
10
sql/log.cc
10
sql/log.cc
@ -4304,6 +4304,10 @@ void MYSQL_BIN_LOG::wait_for_last_checkpoint_event()
|
|||||||
relay log.
|
relay log.
|
||||||
|
|
||||||
IMPLEMENTATION
|
IMPLEMENTATION
|
||||||
|
|
||||||
|
- You must hold rli->data_lock before calling this function, since
|
||||||
|
it writes group_relay_log_pos and similar fields of
|
||||||
|
Relay_log_info.
|
||||||
- Protects index file with LOCK_index
|
- Protects index file with LOCK_index
|
||||||
- Delete relevant relay log files
|
- Delete relevant relay log files
|
||||||
- Copy all file names after these ones to the front of the index file
|
- Copy all file names after these ones to the front of the index file
|
||||||
@ -4317,7 +4321,7 @@ void MYSQL_BIN_LOG::wait_for_last_checkpoint_event()
|
|||||||
read by the SQL slave thread are deleted).
|
read by the SQL slave thread are deleted).
|
||||||
|
|
||||||
@note
|
@note
|
||||||
- This is only called from the slave-execute thread when it has read
|
- This is only called from the slave SQL thread when it has read
|
||||||
all commands from a relay log and want to switch to a new relay log.
|
all commands from a relay log and want to switch to a new relay log.
|
||||||
- When this happens, we can be in an active transaction as
|
- When this happens, we can be in an active transaction as
|
||||||
a transaction can span over two relay logs
|
a transaction can span over two relay logs
|
||||||
@ -4348,6 +4352,8 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included)
|
|||||||
DBUG_ASSERT(rli->slave_running == MYSQL_SLAVE_RUN_NOT_CONNECT);
|
DBUG_ASSERT(rli->slave_running == MYSQL_SLAVE_RUN_NOT_CONNECT);
|
||||||
DBUG_ASSERT(!strcmp(rli->linfo.log_file_name,rli->event_relay_log_name));
|
DBUG_ASSERT(!strcmp(rli->linfo.log_file_name,rli->event_relay_log_name));
|
||||||
|
|
||||||
|
mysql_mutex_assert_owner(&rli->data_lock);
|
||||||
|
|
||||||
mysql_mutex_lock(&LOCK_index);
|
mysql_mutex_lock(&LOCK_index);
|
||||||
|
|
||||||
ir= rli->inuse_relaylog_list;
|
ir= rli->inuse_relaylog_list;
|
||||||
@ -4406,7 +4412,7 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Store where we are in the new file for the execution thread */
|
/* Store where we are in the new file for the execution thread */
|
||||||
flush_relay_log_info(rli);
|
rli->flush();
|
||||||
|
|
||||||
DBUG_EXECUTE_IF("crash_before_purge_logs", DBUG_SUICIDE(););
|
DBUG_EXECUTE_IF("crash_before_purge_logs", DBUG_SUICIDE(););
|
||||||
|
|
||||||
|
@ -966,6 +966,7 @@ int Log_event::do_update_pos(rpl_group_info *rgi)
|
|||||||
Relay_log_info *rli= rgi->rli;
|
Relay_log_info *rli= rgi->rli;
|
||||||
DBUG_ENTER("Log_event::do_update_pos");
|
DBUG_ENTER("Log_event::do_update_pos");
|
||||||
|
|
||||||
|
DBUG_ASSERT(!rli->belongs_to_client());
|
||||||
/*
|
/*
|
||||||
rli is null when (as far as I (Guilhem) know) the caller is
|
rli is null when (as far as I (Guilhem) know) the caller is
|
||||||
Load_log_event::do_apply_event *and* that one is called from
|
Load_log_event::do_apply_event *and* that one is called from
|
||||||
@ -6403,6 +6404,9 @@ bool Rotate_log_event::write()
|
|||||||
in a A -> B -> A setup.
|
in a A -> B -> A setup.
|
||||||
The NOTES below is a wrong comment which will disappear when 4.1 is merged.
|
The NOTES below is a wrong comment which will disappear when 4.1 is merged.
|
||||||
|
|
||||||
|
This must only be called from the Slave SQL thread, since it calls
|
||||||
|
Relay_log_info::flush().
|
||||||
|
|
||||||
@retval
|
@retval
|
||||||
0 ok
|
0 ok
|
||||||
*/
|
*/
|
||||||
@ -6456,7 +6460,7 @@ int Rotate_log_event::do_update_pos(rpl_group_info *rgi)
|
|||||||
(ulong) rli->group_master_log_pos));
|
(ulong) rli->group_master_log_pos));
|
||||||
mysql_mutex_unlock(&rli->data_lock);
|
mysql_mutex_unlock(&rli->data_lock);
|
||||||
rpl_global_gtid_slave_state->record_and_update_gtid(thd, rgi);
|
rpl_global_gtid_slave_state->record_and_update_gtid(thd, rgi);
|
||||||
flush_relay_log_info(rli);
|
rli->flush();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Reset thd->variables.option_bits and sql_mode etc, because this could
|
Reset thd->variables.option_bits and sql_mode etc, because this could
|
||||||
@ -8225,6 +8229,9 @@ void Stop_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
|
|||||||
were we must do this cleaning is in
|
were we must do this cleaning is in
|
||||||
Start_log_event_v3::do_apply_event(), not here. Because if we come
|
Start_log_event_v3::do_apply_event(), not here. Because if we come
|
||||||
here, the master was sane.
|
here, the master was sane.
|
||||||
|
|
||||||
|
This must only be called from the Slave SQL thread, since it calls
|
||||||
|
Relay_log_info::flush().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int Stop_log_event::do_update_pos(rpl_group_info *rgi)
|
int Stop_log_event::do_update_pos(rpl_group_info *rgi)
|
||||||
@ -8244,7 +8251,7 @@ int Stop_log_event::do_update_pos(rpl_group_info *rgi)
|
|||||||
{
|
{
|
||||||
rpl_global_gtid_slave_state->record_and_update_gtid(thd, rgi);
|
rpl_global_gtid_slave_state->record_and_update_gtid(thd, rgi);
|
||||||
rli->inc_group_relay_log_pos(0, rgi);
|
rli->inc_group_relay_log_pos(0, rgi);
|
||||||
flush_relay_log_info(rli);
|
rli->flush();
|
||||||
}
|
}
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include "sql_priv.h"
|
#include "sql_priv.h"
|
||||||
#include <my_dir.h>
|
#include <my_dir.h>
|
||||||
#include "rpl_mi.h"
|
#include "rpl_mi.h"
|
||||||
#include "slave.h" // SLAVE_MAX_HEARTBEAT_PERIOD
|
#include "slave.h"
|
||||||
#include "strfunc.h"
|
#include "strfunc.h"
|
||||||
#include "sql_repl.h"
|
#include "sql_repl.h"
|
||||||
|
|
||||||
@ -647,7 +647,7 @@ file '%s')", fname);
|
|||||||
(ulong) mi->master_log_pos));
|
(ulong) mi->master_log_pos));
|
||||||
|
|
||||||
mi->rli.mi= mi;
|
mi->rli.mi= mi;
|
||||||
if (init_relay_log_info(&mi->rli, slave_info_fname))
|
if (mi->rli.init(slave_info_fname))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
mi->inited = 1;
|
mi->inited = 1;
|
||||||
|
@ -47,9 +47,7 @@ rpt_handle_event(rpl_parallel_thread::queued_event *qev,
|
|||||||
if (!(ev->is_artificial_event() || ev->is_relay_log_event() ||
|
if (!(ev->is_artificial_event() || ev->is_relay_log_event() ||
|
||||||
(ev->when == 0)))
|
(ev->when == 0)))
|
||||||
rgi->last_master_timestamp= ev->when + (time_t)ev->exec_time;
|
rgi->last_master_timestamp= ev->when + (time_t)ev->exec_time;
|
||||||
mysql_mutex_lock(&rli->data_lock);
|
err= apply_event_and_update_pos_for_parallel(ev, thd, rgi);
|
||||||
/* Mutex will be released in apply_event_and_update_pos(). */
|
|
||||||
err= apply_event_and_update_pos(ev, thd, rgi, rpt);
|
|
||||||
|
|
||||||
thread_safe_increment64(&rli->executed_entries);
|
thread_safe_increment64(&rli->executed_entries);
|
||||||
/* ToDo: error handling. */
|
/* ToDo: error handling. */
|
||||||
@ -2426,8 +2424,17 @@ rpl_parallel::do_event(rpl_group_info *serial_rgi, Log_event *ev,
|
|||||||
!(unlikely(rli->gtid_skip_flag != GTID_SKIP_NOT) && is_group_event))
|
!(unlikely(rli->gtid_skip_flag != GTID_SKIP_NOT) && is_group_event))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* ToDo: what to do with this lock?!? */
|
/* Note: rli->data_lock is released by sql_delay_event(). */
|
||||||
mysql_mutex_unlock(&rli->data_lock);
|
if (sql_delay_event(ev, rli->sql_driver_thd, serial_rgi))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
If sql_delay_event() returns non-zero, it means that the wait timed out
|
||||||
|
due to slave stop. We should not queue the event in this case, it must
|
||||||
|
not be applied yet.
|
||||||
|
*/
|
||||||
|
delete ev;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (unlikely(typ == FORMAT_DESCRIPTION_EVENT))
|
if (unlikely(typ == FORMAT_DESCRIPTION_EVENT))
|
||||||
{
|
{
|
||||||
|
258
sql/rpl_rli.cc
258
sql/rpl_rli.cc
@ -29,6 +29,7 @@
|
|||||||
#include "rpl_utility.h"
|
#include "rpl_utility.h"
|
||||||
#include "transaction.h"
|
#include "transaction.h"
|
||||||
#include "sql_parse.h" // end_trans, ROLLBACK
|
#include "sql_parse.h" // end_trans, ROLLBACK
|
||||||
|
#include "slave.h"
|
||||||
#include <mysql/plugin.h>
|
#include <mysql/plugin.h>
|
||||||
#include <mysql/service_thd_wait.h>
|
#include <mysql/service_thd_wait.h>
|
||||||
|
|
||||||
@ -42,30 +43,24 @@ rpl_slave_state *rpl_global_gtid_slave_state;
|
|||||||
/* Object used for MASTER_GTID_WAIT(). */
|
/* Object used for MASTER_GTID_WAIT(). */
|
||||||
gtid_waiting rpl_global_gtid_waiting;
|
gtid_waiting rpl_global_gtid_waiting;
|
||||||
|
|
||||||
|
const char *const Relay_log_info::state_delaying_string = "Waiting until MASTER_DELAY seconds after master executed event";
|
||||||
// Defined in slave.cc
|
|
||||||
int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
|
|
||||||
int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
|
|
||||||
const char *default_val);
|
|
||||||
|
|
||||||
Relay_log_info::Relay_log_info(bool is_slave_recovery)
|
Relay_log_info::Relay_log_info(bool is_slave_recovery)
|
||||||
:Slave_reporting_capability("SQL"),
|
:Slave_reporting_capability("SQL"),
|
||||||
no_storage(FALSE), replicate_same_server_id(::replicate_same_server_id),
|
replicate_same_server_id(::replicate_same_server_id),
|
||||||
info_fd(-1), cur_log_fd(-1), relay_log(&sync_relaylog_period),
|
info_fd(-1), cur_log_fd(-1), relay_log(&sync_relaylog_period),
|
||||||
sync_counter(0), is_relay_log_recovery(is_slave_recovery),
|
sync_counter(0), is_relay_log_recovery(is_slave_recovery),
|
||||||
save_temporary_tables(0),
|
save_temporary_tables(0),
|
||||||
mi(0), inuse_relaylog_list(0), last_inuse_relaylog(0),
|
mi(0), inuse_relaylog_list(0), last_inuse_relaylog(0),
|
||||||
cur_log_old_open_count(0), group_relay_log_pos(0),
|
cur_log_old_open_count(0), group_relay_log_pos(0),
|
||||||
event_relay_log_pos(0),
|
event_relay_log_pos(0),
|
||||||
#if HAVE_valgrind
|
|
||||||
is_fake(FALSE),
|
|
||||||
#endif
|
|
||||||
group_master_log_pos(0), log_space_total(0), ignore_log_space_limit(0),
|
group_master_log_pos(0), log_space_total(0), ignore_log_space_limit(0),
|
||||||
last_master_timestamp(0), sql_thread_caught_up(true), slave_skip_counter(0),
|
last_master_timestamp(0), sql_thread_caught_up(true), slave_skip_counter(0),
|
||||||
abort_pos_wait(0), slave_run_id(0), sql_driver_thd(),
|
abort_pos_wait(0), slave_run_id(0), sql_driver_thd(),
|
||||||
gtid_skip_flag(GTID_SKIP_NOT), inited(0), abort_slave(0), stop_for_until(0),
|
gtid_skip_flag(GTID_SKIP_NOT), inited(0), abort_slave(0), stop_for_until(0),
|
||||||
slave_running(MYSQL_SLAVE_NOT_RUN), until_condition(UNTIL_NONE),
|
slave_running(MYSQL_SLAVE_NOT_RUN), until_condition(UNTIL_NONE),
|
||||||
until_log_pos(0), retried_trans(0), executed_entries(0),
|
until_log_pos(0), retried_trans(0), executed_entries(0),
|
||||||
|
sql_delay(0), sql_delay_end(0),
|
||||||
m_flags(0)
|
m_flags(0)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Relay_log_info::Relay_log_info");
|
DBUG_ENTER("Relay_log_info::Relay_log_info");
|
||||||
@ -117,39 +112,42 @@ Relay_log_info::~Relay_log_info()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int init_relay_log_info(Relay_log_info* rli,
|
/**
|
||||||
const char* info_fname)
|
Read the relay_log.info file.
|
||||||
|
|
||||||
|
@param info_fname The name of the file to read from.
|
||||||
|
@retval 0 success
|
||||||
|
@retval 1 failure
|
||||||
|
*/
|
||||||
|
int Relay_log_info::init(const char* info_fname)
|
||||||
{
|
{
|
||||||
char fname[FN_REFLEN+128];
|
char fname[FN_REFLEN+128];
|
||||||
int info_fd;
|
|
||||||
const char* msg = 0;
|
const char* msg = 0;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
DBUG_ENTER("init_relay_log_info");
|
DBUG_ENTER("Relay_log_info::init");
|
||||||
DBUG_ASSERT(!rli->no_storage); // Don't init if there is no storage
|
|
||||||
|
|
||||||
if (rli->inited) // Set if this function called
|
if (inited) // Set if this function called
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
fn_format(fname, info_fname, mysql_data_home, "", 4+32);
|
fn_format(fname, info_fname, mysql_data_home, "", 4+32);
|
||||||
mysql_mutex_lock(&rli->data_lock);
|
mysql_mutex_lock(&data_lock);
|
||||||
info_fd = rli->info_fd;
|
cur_log_fd = -1;
|
||||||
rli->cur_log_fd = -1;
|
slave_skip_counter=0;
|
||||||
rli->slave_skip_counter=0;
|
abort_pos_wait=0;
|
||||||
rli->abort_pos_wait=0;
|
log_space_limit= relay_log_space_limit;
|
||||||
rli->log_space_limit= relay_log_space_limit;
|
log_space_total= 0;
|
||||||
rli->log_space_total= 0;
|
|
||||||
|
|
||||||
char pattern[FN_REFLEN];
|
char pattern[FN_REFLEN];
|
||||||
(void) my_realpath(pattern, slave_load_tmpdir, 0);
|
(void) my_realpath(pattern, slave_load_tmpdir, 0);
|
||||||
if (fn_format(pattern, PREFIX_SQL_LOAD, pattern, "",
|
if (fn_format(pattern, PREFIX_SQL_LOAD, pattern, "",
|
||||||
MY_SAFE_PATH | MY_RETURN_REAL_PATH) == NullS)
|
MY_SAFE_PATH | MY_RETURN_REAL_PATH) == NullS)
|
||||||
{
|
{
|
||||||
mysql_mutex_unlock(&rli->data_lock);
|
mysql_mutex_unlock(&data_lock);
|
||||||
sql_print_error("Unable to use slave's temporary directory %s",
|
sql_print_error("Unable to use slave's temporary directory %s",
|
||||||
slave_load_tmpdir);
|
slave_load_tmpdir);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
unpack_filename(rli->slave_patternload_file, pattern);
|
unpack_filename(slave_patternload_file, pattern);
|
||||||
rli->slave_patternload_file_size= strlen(rli->slave_patternload_file);
|
slave_patternload_file_size= strlen(slave_patternload_file);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE.
|
The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE.
|
||||||
@ -163,7 +161,7 @@ int init_relay_log_info(Relay_log_info* rli,
|
|||||||
if (opt_relay_logname &&
|
if (opt_relay_logname &&
|
||||||
opt_relay_logname[strlen(opt_relay_logname) - 1] == FN_LIBCHAR)
|
opt_relay_logname[strlen(opt_relay_logname) - 1] == FN_LIBCHAR)
|
||||||
{
|
{
|
||||||
mysql_mutex_unlock(&rli->data_lock);
|
mysql_mutex_unlock(&data_lock);
|
||||||
sql_print_error("Path '%s' is a directory name, please specify \
|
sql_print_error("Path '%s' is a directory name, please specify \
|
||||||
a file name for --relay-log option", opt_relay_logname);
|
a file name for --relay-log option", opt_relay_logname);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
@ -175,7 +173,7 @@ a file name for --relay-log option", opt_relay_logname);
|
|||||||
opt_relaylog_index_name[strlen(opt_relaylog_index_name) - 1]
|
opt_relaylog_index_name[strlen(opt_relaylog_index_name) - 1]
|
||||||
== FN_LIBCHAR)
|
== FN_LIBCHAR)
|
||||||
{
|
{
|
||||||
mysql_mutex_unlock(&rli->data_lock);
|
mysql_mutex_unlock(&data_lock);
|
||||||
sql_print_error("Path '%s' is a directory name, please specify \
|
sql_print_error("Path '%s' is a directory name, please specify \
|
||||||
a file name for --relay-log-index option", opt_relaylog_index_name);
|
a file name for --relay-log-index option", opt_relaylog_index_name);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
@ -184,7 +182,7 @@ a file name for --relay-log-index option", opt_relaylog_index_name);
|
|||||||
char buf[FN_REFLEN];
|
char buf[FN_REFLEN];
|
||||||
const char *ln;
|
const char *ln;
|
||||||
static bool name_warning_sent= 0;
|
static bool name_warning_sent= 0;
|
||||||
ln= rli->relay_log.generate_name(opt_relay_logname, "-relay-bin",
|
ln= relay_log.generate_name(opt_relay_logname, "-relay-bin",
|
||||||
1, buf);
|
1, buf);
|
||||||
/* We send the warning only at startup, not after every RESET SLAVE */
|
/* We send the warning only at startup, not after every RESET SLAVE */
|
||||||
if (!opt_relay_logname && !opt_relaylog_index_name && !name_warning_sent &&
|
if (!opt_relay_logname && !opt_relaylog_index_name && !name_warning_sent &&
|
||||||
@ -207,7 +205,6 @@ a file name for --relay-log-index option", opt_relaylog_index_name);
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* For multimaster, add connection name to relay log filenames */
|
/* For multimaster, add connection name to relay log filenames */
|
||||||
Master_info* mi= rli->mi;
|
|
||||||
char buf_relay_logname[FN_REFLEN], buf_relaylog_index_name_buff[FN_REFLEN];
|
char buf_relay_logname[FN_REFLEN], buf_relaylog_index_name_buff[FN_REFLEN];
|
||||||
char *buf_relaylog_index_name= opt_relaylog_index_name;
|
char *buf_relaylog_index_name= opt_relaylog_index_name;
|
||||||
|
|
||||||
@ -229,12 +226,12 @@ a file name for --relay-log-index option", opt_relaylog_index_name);
|
|||||||
note, that if open() fails, we'll still have index file open
|
note, that if open() fails, we'll still have index file open
|
||||||
but a destructor will take care of that
|
but a destructor will take care of that
|
||||||
*/
|
*/
|
||||||
if (rli->relay_log.open_index_file(buf_relaylog_index_name, ln, TRUE) ||
|
if (relay_log.open_index_file(buf_relaylog_index_name, ln, TRUE) ||
|
||||||
rli->relay_log.open(ln, LOG_BIN, 0, 0, SEQ_READ_APPEND,
|
relay_log.open(ln, LOG_BIN, 0, 0, SEQ_READ_APPEND,
|
||||||
mi->rli.max_relay_log_size, 1, TRUE))
|
max_relay_log_size, 1, TRUE))
|
||||||
{
|
{
|
||||||
mysql_mutex_unlock(&rli->data_lock);
|
mysql_mutex_unlock(&data_lock);
|
||||||
sql_print_error("Failed when trying to open logs for '%s' in init_relay_log_info(). Error: %M", ln, my_errno);
|
sql_print_error("Failed when trying to open logs for '%s' in Relay_log_info::init(). Error: %M", ln, my_errno);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -256,7 +253,7 @@ file '%s', errno %d)", fname, my_errno);
|
|||||||
msg= current_thd->get_stmt_da()->message();
|
msg= current_thd->get_stmt_da()->message();
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (init_io_cache(&rli->info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0,
|
if (init_io_cache(&info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0,
|
||||||
MYF(MY_WME)))
|
MYF(MY_WME)))
|
||||||
{
|
{
|
||||||
sql_print_error("Failed to create a cache on relay log info file '%s'",
|
sql_print_error("Failed to create a cache on relay log info file '%s'",
|
||||||
@ -266,20 +263,19 @@ file '%s', errno %d)", fname, my_errno);
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Init relay log with first entry in the relay index file */
|
/* Init relay log with first entry in the relay index file */
|
||||||
if (init_relay_log_pos(rli,NullS,BIN_LOG_HEADER_SIZE,0 /* no data lock */,
|
if (init_relay_log_pos(this,NullS,BIN_LOG_HEADER_SIZE,0 /* no data lock */,
|
||||||
&msg, 0))
|
&msg, 0))
|
||||||
{
|
{
|
||||||
sql_print_error("Failed to open the relay log 'FIRST' (relay_log_pos 4)");
|
sql_print_error("Failed to open the relay log 'FIRST' (relay_log_pos 4)");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
rli->group_master_log_name[0]= 0;
|
group_master_log_name[0]= 0;
|
||||||
rli->group_master_log_pos= 0;
|
group_master_log_pos= 0;
|
||||||
rli->info_fd= info_fd;
|
|
||||||
}
|
}
|
||||||
else // file exists
|
else // file exists
|
||||||
{
|
{
|
||||||
if (info_fd >= 0)
|
if (info_fd >= 0)
|
||||||
reinit_io_cache(&rli->info_file, READ_CACHE, 0L,0,0);
|
reinit_io_cache(&info_file, READ_CACHE, 0L,0,0);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int error=0;
|
int error=0;
|
||||||
@ -291,7 +287,7 @@ Failed to open the existing relay log info file '%s' (errno %d)",
|
|||||||
fname, my_errno);
|
fname, my_errno);
|
||||||
error= 1;
|
error= 1;
|
||||||
}
|
}
|
||||||
else if (init_io_cache(&rli->info_file, info_fd,
|
else if (init_io_cache(&info_file, info_fd,
|
||||||
IO_SIZE*2, READ_CACHE, 0L, 0, MYF(MY_WME)))
|
IO_SIZE*2, READ_CACHE, 0L, 0, MYF(MY_WME)))
|
||||||
{
|
{
|
||||||
sql_print_error("Failed to create a cache on relay log info file '%s'",
|
sql_print_error("Failed to create a cache on relay log info file '%s'",
|
||||||
@ -302,24 +298,15 @@ Failed to open the existing relay log info file '%s' (errno %d)",
|
|||||||
{
|
{
|
||||||
if (info_fd >= 0)
|
if (info_fd >= 0)
|
||||||
mysql_file_close(info_fd, MYF(0));
|
mysql_file_close(info_fd, MYF(0));
|
||||||
rli->info_fd= -1;
|
info_fd= -1;
|
||||||
rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
|
relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
|
||||||
mysql_mutex_unlock(&rli->data_lock);
|
mysql_mutex_unlock(&data_lock);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rli->info_fd = info_fd;
|
|
||||||
int relay_log_pos, master_log_pos, lines;
|
int relay_log_pos, master_log_pos, lines;
|
||||||
char *first_non_digit;
|
char *first_non_digit;
|
||||||
/*
|
|
||||||
In MySQL 5.6, there is a MASTER_DELAY option to CHANGE MASTER. This is
|
|
||||||
not yet merged into MariaDB (as of 10.0.13). However, we detect the
|
|
||||||
presense of the new option in relay-log.info, as a placeholder for
|
|
||||||
possible later merge of the feature, and to maintain file format
|
|
||||||
compatibility with MySQL 5.6+.
|
|
||||||
*/
|
|
||||||
int dummy_sql_delay;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Starting from MySQL 5.6.x, relay-log.info has a new format.
|
Starting from MySQL 5.6.x, relay-log.info has a new format.
|
||||||
@ -344,25 +331,25 @@ Failed to open the existing relay log info file '%s' (errno %d)",
|
|||||||
it is line count and not binlog name (new format) it will be
|
it is line count and not binlog name (new format) it will be
|
||||||
overwritten by the second row later.
|
overwritten by the second row later.
|
||||||
*/
|
*/
|
||||||
if (init_strvar_from_file(rli->group_relay_log_name,
|
if (init_strvar_from_file(group_relay_log_name,
|
||||||
sizeof(rli->group_relay_log_name),
|
sizeof(group_relay_log_name),
|
||||||
&rli->info_file, ""))
|
&info_file, ""))
|
||||||
{
|
{
|
||||||
msg="Error reading slave log configuration";
|
msg="Error reading slave log configuration";
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
lines= strtoul(rli->group_relay_log_name, &first_non_digit, 10);
|
lines= strtoul(group_relay_log_name, &first_non_digit, 10);
|
||||||
|
|
||||||
if (rli->group_relay_log_name[0] != '\0' &&
|
if (group_relay_log_name[0] != '\0' &&
|
||||||
*first_non_digit == '\0' &&
|
*first_non_digit == '\0' &&
|
||||||
lines >= LINES_IN_RELAY_LOG_INFO_WITH_DELAY)
|
lines >= LINES_IN_RELAY_LOG_INFO_WITH_DELAY)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("relay_log_info file is in new format."));
|
DBUG_PRINT("info", ("relay_log_info file is in new format."));
|
||||||
/* Seems to be new format => read relay log name from next line */
|
/* Seems to be new format => read relay log name from next line */
|
||||||
if (init_strvar_from_file(rli->group_relay_log_name,
|
if (init_strvar_from_file(group_relay_log_name,
|
||||||
sizeof(rli->group_relay_log_name),
|
sizeof(group_relay_log_name),
|
||||||
&rli->info_file, ""))
|
&info_file, ""))
|
||||||
{
|
{
|
||||||
msg="Error reading slave log configuration";
|
msg="Error reading slave log configuration";
|
||||||
goto err;
|
goto err;
|
||||||
@ -372,70 +359,70 @@ Failed to open the existing relay log info file '%s' (errno %d)",
|
|||||||
DBUG_PRINT("info", ("relay_log_info file is in old format."));
|
DBUG_PRINT("info", ("relay_log_info file is in old format."));
|
||||||
|
|
||||||
if (init_intvar_from_file(&relay_log_pos,
|
if (init_intvar_from_file(&relay_log_pos,
|
||||||
&rli->info_file, BIN_LOG_HEADER_SIZE) ||
|
&info_file, BIN_LOG_HEADER_SIZE) ||
|
||||||
init_strvar_from_file(rli->group_master_log_name,
|
init_strvar_from_file(group_master_log_name,
|
||||||
sizeof(rli->group_master_log_name),
|
sizeof(group_master_log_name),
|
||||||
&rli->info_file, "") ||
|
&info_file, "") ||
|
||||||
init_intvar_from_file(&master_log_pos, &rli->info_file, 0) ||
|
init_intvar_from_file(&master_log_pos, &info_file, 0) ||
|
||||||
(lines >= LINES_IN_RELAY_LOG_INFO_WITH_DELAY &&
|
(lines >= LINES_IN_RELAY_LOG_INFO_WITH_DELAY &&
|
||||||
init_intvar_from_file(&dummy_sql_delay, &rli->info_file, 0)))
|
init_intvar_from_file(&sql_delay, &info_file, 0)))
|
||||||
{
|
{
|
||||||
msg="Error reading slave log configuration";
|
msg="Error reading slave log configuration";
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
strmake_buf(rli->event_relay_log_name,rli->group_relay_log_name);
|
strmake_buf(event_relay_log_name,group_relay_log_name);
|
||||||
rli->group_relay_log_pos= rli->event_relay_log_pos= relay_log_pos;
|
group_relay_log_pos= event_relay_log_pos= relay_log_pos;
|
||||||
rli->group_master_log_pos= master_log_pos;
|
group_master_log_pos= master_log_pos;
|
||||||
|
|
||||||
if (rli->is_relay_log_recovery && init_recovery(rli->mi, &msg))
|
if (is_relay_log_recovery && init_recovery(mi, &msg))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
rli->relay_log_state.load(rpl_global_gtid_slave_state);
|
relay_log_state.load(rpl_global_gtid_slave_state);
|
||||||
if (init_relay_log_pos(rli,
|
if (init_relay_log_pos(this,
|
||||||
rli->group_relay_log_name,
|
group_relay_log_name,
|
||||||
rli->group_relay_log_pos,
|
group_relay_log_pos,
|
||||||
0 /* no data lock*/,
|
0 /* no data lock*/,
|
||||||
&msg, 0))
|
&msg, 0))
|
||||||
{
|
{
|
||||||
sql_print_error("Failed to open the relay log '%s' (relay_log_pos %llu)",
|
sql_print_error("Failed to open the relay log '%s' (relay_log_pos %llu)",
|
||||||
rli->group_relay_log_name, rli->group_relay_log_pos);
|
group_relay_log_name, group_relay_log_pos);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_PRINT("info", ("my_b_tell(rli->cur_log)=%llu rli->event_relay_log_pos=%llu",
|
DBUG_PRINT("info", ("my_b_tell(cur_log)=%llu event_relay_log_pos=%llu",
|
||||||
my_b_tell(rli->cur_log), rli->event_relay_log_pos));
|
my_b_tell(cur_log), event_relay_log_pos));
|
||||||
DBUG_ASSERT(rli->event_relay_log_pos >= BIN_LOG_HEADER_SIZE);
|
DBUG_ASSERT(event_relay_log_pos >= BIN_LOG_HEADER_SIZE);
|
||||||
DBUG_ASSERT(my_b_tell(rli->cur_log) == rli->event_relay_log_pos);
|
DBUG_ASSERT(my_b_tell(cur_log) == event_relay_log_pos);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Now change the cache from READ to WRITE - must do this
|
Now change the cache from READ to WRITE - must do this
|
||||||
before flush_relay_log_info
|
before Relay_log_info::flush()
|
||||||
*/
|
*/
|
||||||
reinit_io_cache(&rli->info_file, WRITE_CACHE,0L,0,1);
|
reinit_io_cache(&info_file, WRITE_CACHE,0L,0,1);
|
||||||
if ((error= flush_relay_log_info(rli)))
|
if ((error= flush()))
|
||||||
{
|
{
|
||||||
msg= "Failed to flush relay log info file";
|
msg= "Failed to flush relay log info file";
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (count_relay_log_space(rli))
|
if (count_relay_log_space(this))
|
||||||
{
|
{
|
||||||
msg="Error counting relay log space";
|
msg="Error counting relay log space";
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
rli->inited= 1;
|
inited= 1;
|
||||||
mysql_mutex_unlock(&rli->data_lock);
|
mysql_mutex_unlock(&data_lock);
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
sql_print_error("%s", msg);
|
sql_print_error("%s", msg);
|
||||||
end_io_cache(&rli->info_file);
|
end_io_cache(&info_file);
|
||||||
if (info_fd >= 0)
|
if (info_fd >= 0)
|
||||||
mysql_file_close(info_fd, MYF(0));
|
mysql_file_close(info_fd, MYF(0));
|
||||||
rli->info_fd= -1;
|
info_fd= -1;
|
||||||
rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
|
relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
|
||||||
mysql_mutex_unlock(&rli->data_lock);
|
mysql_mutex_unlock(&data_lock);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -752,6 +739,8 @@ err:
|
|||||||
if (!rli->relay_log.description_event_for_exec->is_valid() && !*errmsg)
|
if (!rli->relay_log.description_event_for_exec->is_valid() && !*errmsg)
|
||||||
*errmsg= "Invalid Format_description log event; could be out of memory";
|
*errmsg= "Invalid Format_description log event; could be out of memory";
|
||||||
|
|
||||||
|
DBUG_PRINT("info", ("Returning %d from init_relay_log_pos", (*errmsg)?1:0));
|
||||||
|
|
||||||
DBUG_RETURN ((*errmsg) ? 1 : 0);
|
DBUG_RETURN ((*errmsg) ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -969,8 +958,11 @@ void Relay_log_info::inc_group_relay_log_pos(ulonglong log_pos,
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("Relay_log_info::inc_group_relay_log_pos");
|
DBUG_ENTER("Relay_log_info::inc_group_relay_log_pos");
|
||||||
|
|
||||||
if (!skip_lock)
|
if (skip_lock)
|
||||||
|
mysql_mutex_assert_owner(&data_lock);
|
||||||
|
else
|
||||||
mysql_mutex_lock(&data_lock);
|
mysql_mutex_lock(&data_lock);
|
||||||
|
|
||||||
rgi->inc_event_relay_log_pos();
|
rgi->inc_event_relay_log_pos();
|
||||||
DBUG_PRINT("info", ("log_pos: %lu group_master_log_pos: %lu",
|
DBUG_PRINT("info", ("log_pos: %lu group_master_log_pos: %lu",
|
||||||
(long) log_pos, (long) group_master_log_pos));
|
(long) log_pos, (long) group_master_log_pos));
|
||||||
@ -1134,10 +1126,10 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset,
|
|||||||
Indeed, rli->inited==0 does not imply that they already are empty.
|
Indeed, rli->inited==0 does not imply that they already are empty.
|
||||||
It could be that slave's info initialization partly succeeded :
|
It could be that slave's info initialization partly succeeded :
|
||||||
for example if relay-log.info existed but *relay-bin*.*
|
for example if relay-log.info existed but *relay-bin*.*
|
||||||
have been manually removed, init_relay_log_info reads the old
|
have been manually removed, Relay_log_info::init() reads the old
|
||||||
relay-log.info and fills rli->master_log_*, then init_relay_log_info
|
relay-log.info and fills rli->master_log_*, then Relay_log_info::init()
|
||||||
checks for the existence of the relay log, this fails and
|
checks for the existence of the relay log, this fails and
|
||||||
init_relay_log_info leaves rli->inited to 0.
|
Relay_log_info::init() leaves rli->inited to 0.
|
||||||
In that pathological case, rli->master_log_pos* will be properly reinited
|
In that pathological case, rli->master_log_pos* will be properly reinited
|
||||||
at the next START SLAVE (as RESET SLAVE or CHANGE
|
at the next START SLAVE (as RESET SLAVE or CHANGE
|
||||||
MASTER, the callers of purge_relay_logs, will delete bogus *.info files
|
MASTER, the callers of purge_relay_logs, will delete bogus *.info files
|
||||||
@ -1325,6 +1317,7 @@ void Relay_log_info::stmt_done(my_off_t event_master_log_pos, THD *thd,
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("Relay_log_info::stmt_done");
|
DBUG_ENTER("Relay_log_info::stmt_done");
|
||||||
|
|
||||||
|
DBUG_ASSERT(!belongs_to_client());
|
||||||
DBUG_ASSERT(rgi->rli == this);
|
DBUG_ASSERT(rgi->rli == this);
|
||||||
/*
|
/*
|
||||||
If in a transaction, and if the slave supports transactions, just
|
If in a transaction, and if the slave supports transactions, just
|
||||||
@ -1374,7 +1367,7 @@ void Relay_log_info::stmt_done(my_off_t event_master_log_pos, THD *thd,
|
|||||||
}
|
}
|
||||||
DBUG_EXECUTE_IF("inject_crash_before_flush_rli", DBUG_SUICIDE(););
|
DBUG_EXECUTE_IF("inject_crash_before_flush_rli", DBUG_SUICIDE(););
|
||||||
if (mi->using_gtid == Master_info::USE_GTID_NO)
|
if (mi->using_gtid == Master_info::USE_GTID_NO)
|
||||||
flush_relay_log_info(this);
|
flush();
|
||||||
DBUG_EXECUTE_IF("inject_crash_after_flush_rli", DBUG_SUICIDE(););
|
DBUG_EXECUTE_IF("inject_crash_after_flush_rli", DBUG_SUICIDE(););
|
||||||
}
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
@ -2037,4 +2030,79 @@ bool rpl_sql_thread_info::cached_charset_compare(char *charset) const
|
|||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Store the file and position where the slave's SQL thread are in the
|
||||||
|
relay log.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
- This function should be called either from the slave SQL thread,
|
||||||
|
or when the slave thread is not running. (It reads the
|
||||||
|
group_{relay|master}_log_{pos|name} and delay fields in the rli
|
||||||
|
object. These may only be modified by the slave SQL thread or by
|
||||||
|
a client thread when the slave SQL thread is not running.)
|
||||||
|
|
||||||
|
- If there is an active transaction, then we do not update the
|
||||||
|
position in the relay log. This is to ensure that we re-execute
|
||||||
|
statements if we die in the middle of an transaction that was
|
||||||
|
rolled back.
|
||||||
|
|
||||||
|
- As a transaction never spans binary logs, we don't have to handle
|
||||||
|
the case where we do a relay-log-rotation in the middle of the
|
||||||
|
transaction. If transactions could span several binlogs, we would
|
||||||
|
have to ensure that we do not delete the relay log file where the
|
||||||
|
transaction started before switching to a new relay log file.
|
||||||
|
|
||||||
|
- Error can happen if writing to file fails or if flushing the file
|
||||||
|
fails.
|
||||||
|
|
||||||
|
@param rli The object representing the Relay_log_info.
|
||||||
|
|
||||||
|
@todo Change the log file information to a binary format to avoid
|
||||||
|
calling longlong2str.
|
||||||
|
|
||||||
|
@return 0 on success, 1 on error.
|
||||||
|
*/
|
||||||
|
bool Relay_log_info::flush()
|
||||||
|
{
|
||||||
|
bool error=0;
|
||||||
|
|
||||||
|
DBUG_ENTER("Relay_log_info::flush()");
|
||||||
|
|
||||||
|
IO_CACHE *file = &info_file;
|
||||||
|
// 2*file name, 2*long long, 2*unsigned long, 6*'\n'
|
||||||
|
char buff[FN_REFLEN * 2 + 22 * 2 + 10 * 2 + 6], *pos;
|
||||||
|
my_b_seek(file, 0L);
|
||||||
|
pos= longlong10_to_str(LINES_IN_RELAY_LOG_INFO_WITH_DELAY, buff, 10);
|
||||||
|
*pos++='\n';
|
||||||
|
pos=strmov(pos, group_relay_log_name);
|
||||||
|
*pos++='\n';
|
||||||
|
pos=longlong10_to_str(group_relay_log_pos, pos, 10);
|
||||||
|
*pos++='\n';
|
||||||
|
pos=strmov(pos, group_master_log_name);
|
||||||
|
*pos++='\n';
|
||||||
|
pos=longlong10_to_str(group_master_log_pos, pos, 10);
|
||||||
|
*pos++='\n';
|
||||||
|
pos= longlong10_to_str(sql_delay, pos, 10);
|
||||||
|
*pos++= '\n';
|
||||||
|
if (my_b_write(file, (uchar*) buff, (size_t) (pos-buff)))
|
||||||
|
error=1;
|
||||||
|
if (flush_io_cache(file))
|
||||||
|
error=1;
|
||||||
|
if (sync_relayloginfo_period &&
|
||||||
|
!error &&
|
||||||
|
++sync_counter >= sync_relayloginfo_period)
|
||||||
|
{
|
||||||
|
if (my_sync(info_fd, MYF(MY_WME)))
|
||||||
|
error=1;
|
||||||
|
sync_counter= 0;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Flushing the relay log is done by the slave I/O thread
|
||||||
|
or by the user on STOP SLAVE.
|
||||||
|
*/
|
||||||
|
DBUG_RETURN(error);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
112
sql/rpl_rli.h
112
sql/rpl_rli.h
@ -29,11 +29,6 @@ class Master_info;
|
|||||||
class Rpl_filter;
|
class Rpl_filter;
|
||||||
|
|
||||||
|
|
||||||
enum {
|
|
||||||
LINES_IN_RELAY_LOG_INFO_WITH_DELAY= 5
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|
||||||
Replication SQL Thread
|
Replication SQL Thread
|
||||||
@ -47,7 +42,7 @@ enum {
|
|||||||
|
|
||||||
Relay_log_info is initialized from the slave.info file if such
|
Relay_log_info is initialized from the slave.info file if such
|
||||||
exists. Otherwise, data members are intialized with defaults. The
|
exists. Otherwise, data members are intialized with defaults. The
|
||||||
initialization is done with init_relay_log_info() call.
|
initialization is done with Relay_log_info::init() call.
|
||||||
|
|
||||||
The format of slave.info file:
|
The format of slave.info file:
|
||||||
|
|
||||||
@ -78,11 +73,17 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If flag set, then rli does not store its state in any info file.
|
The SQL thread owns one Relay_log_info, and each client that has
|
||||||
This is the case only when we execute BINLOG SQL commands inside
|
executed a BINLOG statement owns one Relay_log_info. This function
|
||||||
a client, non-replication thread.
|
returns zero for the Relay_log_info object that belongs to the SQL
|
||||||
|
thread and nonzero for Relay_log_info objects that belong to
|
||||||
|
clients.
|
||||||
*/
|
*/
|
||||||
bool no_storage;
|
inline bool belongs_to_client()
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(sql_driver_thd);
|
||||||
|
return !sql_driver_thd->slave_thread;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If true, events with the same server id should be replicated. This
|
If true, events with the same server id should be replicated. This
|
||||||
@ -194,6 +195,11 @@ public:
|
|||||||
relay log and finishing (commiting) on another relay log. Case which can
|
relay log and finishing (commiting) on another relay log. Case which can
|
||||||
happen when, for example, the relay log gets rotated because of
|
happen when, for example, the relay log gets rotated because of
|
||||||
max_binlog_size.
|
max_binlog_size.
|
||||||
|
|
||||||
|
Note: group_relay_log_name, group_relay_log_pos must only be
|
||||||
|
written from the thread owning the Relay_log_info (SQL thread if
|
||||||
|
!belongs_to_client(); client thread executing BINLOG statement if
|
||||||
|
belongs_to_client()).
|
||||||
*/
|
*/
|
||||||
char group_relay_log_name[FN_REFLEN];
|
char group_relay_log_name[FN_REFLEN];
|
||||||
ulonglong group_relay_log_pos;
|
ulonglong group_relay_log_pos;
|
||||||
@ -205,16 +211,17 @@ public:
|
|||||||
*/
|
*/
|
||||||
char future_event_master_log_name[FN_REFLEN];
|
char future_event_master_log_name[FN_REFLEN];
|
||||||
|
|
||||||
#ifdef HAVE_valgrind
|
|
||||||
bool is_fake; /* Mark that this is a fake relay log info structure */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Original log name and position of the group we're currently executing
|
Original log name and position of the group we're currently executing
|
||||||
(whose coordinates are group_relay_log_name/pos in the relay log)
|
(whose coordinates are group_relay_log_name/pos in the relay log)
|
||||||
in the master's binlog. These concern the *group*, because in the master's
|
in the master's binlog. These concern the *group*, because in the master's
|
||||||
binlog the log_pos that comes with each event is the position of the
|
binlog the log_pos that comes with each event is the position of the
|
||||||
beginning of the group.
|
beginning of the group.
|
||||||
|
|
||||||
|
Note: group_master_log_name, group_master_log_pos must only be
|
||||||
|
written from the thread owning the Relay_log_info (SQL thread if
|
||||||
|
!belongs_to_client(); client thread executing BINLOG statement if
|
||||||
|
belongs_to_client()).
|
||||||
*/
|
*/
|
||||||
char group_master_log_name[FN_REFLEN];
|
char group_master_log_name[FN_REFLEN];
|
||||||
volatile my_off_t group_master_log_pos;
|
volatile my_off_t group_master_log_pos;
|
||||||
@ -244,6 +251,15 @@ public:
|
|||||||
bool sql_thread_caught_up;
|
bool sql_thread_caught_up;
|
||||||
|
|
||||||
void clear_until_condition();
|
void clear_until_condition();
|
||||||
|
/**
|
||||||
|
Reset the delay.
|
||||||
|
This is used by RESET SLAVE to clear the delay.
|
||||||
|
*/
|
||||||
|
void clear_sql_delay()
|
||||||
|
{
|
||||||
|
sql_delay= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Needed for problems when slave stops and we want to restart it
|
Needed for problems when slave stops and we want to restart it
|
||||||
@ -475,8 +491,72 @@ public:
|
|||||||
m_flags&= ~flag;
|
m_flags&= ~flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Text used in THD::proc_info when the slave SQL thread is delaying.
|
||||||
|
*/
|
||||||
|
static const char *const state_delaying_string;
|
||||||
|
|
||||||
|
bool flush();
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reads the relay_log.info file.
|
||||||
|
*/
|
||||||
|
int init(const char* info_filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Indicate that a delay starts.
|
||||||
|
|
||||||
|
This does not actually sleep; it only sets the state of this
|
||||||
|
Relay_log_info object to delaying so that the correct state can be
|
||||||
|
reported by SHOW SLAVE STATUS and SHOW PROCESSLIST.
|
||||||
|
|
||||||
|
Requires rli->data_lock.
|
||||||
|
|
||||||
|
@param delay_end The time when the delay shall end.
|
||||||
|
*/
|
||||||
|
void start_sql_delay(time_t delay_end)
|
||||||
|
{
|
||||||
|
mysql_mutex_assert_owner(&data_lock);
|
||||||
|
sql_delay_end= delay_end;
|
||||||
|
thd_proc_info(sql_driver_thd, state_delaying_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 get_sql_delay() { return sql_delay; }
|
||||||
|
void set_sql_delay(time_t _sql_delay) { sql_delay= _sql_delay; }
|
||||||
|
time_t get_sql_delay_end() { return sql_delay_end; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Delay slave SQL thread by this amount, compared to master (in
|
||||||
|
seconds). This is set with CHANGE MASTER TO MASTER_DELAY=X.
|
||||||
|
|
||||||
|
Guarded by data_lock. Initialized by the client thread executing
|
||||||
|
START SLAVE. Written by client threads executing CHANGE MASTER TO
|
||||||
|
MASTER_DELAY=X. Read by SQL thread and by client threads
|
||||||
|
executing SHOW SLAVE STATUS. Note: must not be written while the
|
||||||
|
slave SQL thread is running, since the SQL thread reads it without
|
||||||
|
a lock when executing Relay_log_info::flush().
|
||||||
|
*/
|
||||||
|
int sql_delay;
|
||||||
|
|
||||||
|
/**
|
||||||
|
During a delay, specifies the point in time when the delay ends.
|
||||||
|
|
||||||
|
This is used for the SQL_Remaining_Delay column in SHOW SLAVE STATUS.
|
||||||
|
|
||||||
|
Guarded by data_lock. Written by the sql thread. Read by client
|
||||||
|
threads executing SHOW SLAVE STATUS.
|
||||||
|
*/
|
||||||
|
time_t sql_delay_end;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Before the MASTER_DELAY parameter was added (WL#344),
|
||||||
|
relay_log.info had 4 lines. Now it has 5 lines.
|
||||||
|
*/
|
||||||
|
static const int LINES_IN_RELAY_LOG_INFO_WITH_DELAY= 5;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Holds the state of the data in the relay log.
|
Holds the state of the data in the relay log.
|
||||||
We need this to ensure that we are not in the middle of a
|
We need this to ensure that we are not in the middle of a
|
||||||
@ -875,10 +955,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Defined in rpl_rli.cc
|
|
||||||
int init_relay_log_info(Relay_log_info* rli, const char* info_fname);
|
|
||||||
|
|
||||||
|
|
||||||
extern struct rpl_slave_state *rpl_global_gtid_slave_state;
|
extern struct rpl_slave_state *rpl_global_gtid_slave_state;
|
||||||
extern gtid_waiting rpl_global_gtid_waiting;
|
extern gtid_waiting rpl_global_gtid_waiting;
|
||||||
|
|
||||||
|
332
sql/slave.cc
332
sql/slave.cc
@ -735,7 +735,7 @@ int terminate_slave_threads(Master_info* mi,int thread_mask,bool skip_lock)
|
|||||||
DBUG_PRINT("info",("Flushing relay-log info file."));
|
DBUG_PRINT("info",("Flushing relay-log info file."));
|
||||||
if (current_thd)
|
if (current_thd)
|
||||||
THD_STAGE_INFO(current_thd, stage_flushing_relay_log_info_file);
|
THD_STAGE_INFO(current_thd, stage_flushing_relay_log_info_file);
|
||||||
if (flush_relay_log_info(&mi->rli))
|
if (mi->rli.flush())
|
||||||
DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS);
|
DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS);
|
||||||
|
|
||||||
if (my_sync(mi->rli.info_fd, MYF(MY_WME)))
|
if (my_sync(mi->rli.info_fd, MYF(MY_WME)))
|
||||||
@ -1631,8 +1631,10 @@ static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi)
|
|||||||
(master_res= mysql_store_result(mysql)) &&
|
(master_res= mysql_store_result(mysql)) &&
|
||||||
(master_row= mysql_fetch_row(master_res)))
|
(master_row= mysql_fetch_row(master_res)))
|
||||||
{
|
{
|
||||||
|
mysql_mutex_lock(&mi->data_lock);
|
||||||
mi->clock_diff_with_master=
|
mi->clock_diff_with_master=
|
||||||
(long) (time((time_t*) 0) - strtoul(master_row[0], 0, 10));
|
(long) (time((time_t*) 0) - strtoul(master_row[0], 0, 10));
|
||||||
|
mysql_mutex_unlock(&mi->data_lock);
|
||||||
}
|
}
|
||||||
else if (check_io_slave_killed(mi, NULL))
|
else if (check_io_slave_killed(mi, NULL))
|
||||||
goto slave_killed_err;
|
goto slave_killed_err;
|
||||||
@ -1644,7 +1646,9 @@ static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
mysql_mutex_lock(&mi->data_lock);
|
||||||
mi->clock_diff_with_master= 0; /* The "most sensible" value */
|
mi->clock_diff_with_master= 0; /* The "most sensible" value */
|
||||||
|
mysql_mutex_unlock(&mi->data_lock);
|
||||||
sql_print_warning("\"SELECT UNIX_TIMESTAMP()\" failed on master, "
|
sql_print_warning("\"SELECT UNIX_TIMESTAMP()\" failed on master, "
|
||||||
"do not trust column Seconds_Behind_Master of SHOW "
|
"do not trust column Seconds_Behind_Master of SHOW "
|
||||||
"SLAVE STATUS. Error: %s (%d)",
|
"SLAVE STATUS. Error: %s (%d)",
|
||||||
@ -2794,6 +2798,15 @@ void show_master_info_get_fields(THD *thd, List<Item> *field_list,
|
|||||||
Item_empty_string(thd, "Parallel_Mode",
|
Item_empty_string(thd, "Parallel_Mode",
|
||||||
sizeof("conservative")-1),
|
sizeof("conservative")-1),
|
||||||
mem_root);
|
mem_root);
|
||||||
|
field_list->push_back(new (mem_root)
|
||||||
|
Item_return_int(thd, "SQL_Delay", 10,
|
||||||
|
MYSQL_TYPE_LONG));
|
||||||
|
field_list->push_back(new (mem_root)
|
||||||
|
Item_return_int(thd, "SQL_Remaining_Delay", 8,
|
||||||
|
MYSQL_TYPE_LONG));
|
||||||
|
field_list->push_back(new (mem_root)
|
||||||
|
Item_empty_string(thd, "Slave_SQL_Running_State",
|
||||||
|
20));
|
||||||
if (full)
|
if (full)
|
||||||
{
|
{
|
||||||
field_list->push_back(new (mem_root)
|
field_list->push_back(new (mem_root)
|
||||||
@ -2983,6 +2996,7 @@ static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full,
|
|||||||
prot_store_ids(thd, &mi->ignore_server_ids);
|
prot_store_ids(thd, &mi->ignore_server_ids);
|
||||||
// Master_Server_id
|
// Master_Server_id
|
||||||
protocol->store((uint32) mi->master_id);
|
protocol->store((uint32) mi->master_id);
|
||||||
|
// SQL_Delay
|
||||||
// Master_Ssl_Crl
|
// Master_Ssl_Crl
|
||||||
protocol->store(mi->ssl_ca, &my_charset_bin);
|
protocol->store(mi->ssl_ca, &my_charset_bin);
|
||||||
// Master_Ssl_Crlpath
|
// Master_Ssl_Crlpath
|
||||||
@ -3005,6 +3019,22 @@ static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full,
|
|||||||
protocol->store(mode_name, strlen(mode_name), &my_charset_bin);
|
protocol->store(mode_name, strlen(mode_name), &my_charset_bin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protocol->store((uint32) mi->rli.get_sql_delay());
|
||||||
|
// SQL_Remaining_Delay
|
||||||
|
// THD::proc_info is not protected by any lock, so we read it once
|
||||||
|
// to ensure that we use the same value throughout this function.
|
||||||
|
const char *slave_sql_running_state=
|
||||||
|
mi->rli.sql_driver_thd ? mi->rli.sql_driver_thd->proc_info : "";
|
||||||
|
if (slave_sql_running_state == Relay_log_info::state_delaying_string)
|
||||||
|
{
|
||||||
|
time_t t= my_time(0), sql_delay_end= mi->rli.get_sql_delay_end();
|
||||||
|
protocol->store((uint32)(t < sql_delay_end ? sql_delay_end - t : 0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
protocol->store_null();
|
||||||
|
// Slave_SQL_Running_State
|
||||||
|
protocol->store(slave_sql_running_state, &my_charset_bin);
|
||||||
|
|
||||||
if (full)
|
if (full)
|
||||||
{
|
{
|
||||||
protocol->store((uint32) mi->rli.retried_trans);
|
protocol->store((uint32) mi->rli.retried_trans);
|
||||||
@ -3369,38 +3399,83 @@ has_temporary_error(THD *thd)
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Applies the given event and advances the relay log position.
|
If this is a lagging slave (specified with CHANGE MASTER TO MASTER_DELAY = X), delays accordingly. Also unlocks rli->data_lock.
|
||||||
|
|
||||||
In essence, this function does:
|
Design note: this is the place to unlock rli->data_lock. The lock
|
||||||
|
must be held when reading delay info from rli, but it should not be
|
||||||
|
held while sleeping.
|
||||||
|
|
||||||
@code
|
@param ev Event that is about to be executed.
|
||||||
ev->apply_event(rli);
|
|
||||||
ev->update_pos(rli);
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
But it also does some maintainance, such as skipping events if
|
@param thd The sql thread's THD object.
|
||||||
needed and reporting errors.
|
|
||||||
|
|
||||||
If the @c skip flag is set, then it is tested whether the event
|
@param rli The sql thread's Relay_log_info structure.
|
||||||
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.
|
|
||||||
|
|
||||||
@retval 0 OK.
|
@retval 0 If the delay timed out and the event shall be executed.
|
||||||
|
|
||||||
@retval 1 Error calling ev->apply_event().
|
@retval nonzero If the delay was interrupted and the event shall be skipped.
|
||||||
|
|
||||||
@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,
|
int
|
||||||
rpl_group_info *rgi,
|
sql_delay_event(Log_event *ev, THD *thd, rpl_group_info *rgi)
|
||||||
rpl_parallel_thread *rpt)
|
|
||||||
{
|
{
|
||||||
int exec_res= 0;
|
|
||||||
Relay_log_info* rli= rgi->rli;
|
Relay_log_info* rli= rgi->rli;
|
||||||
DBUG_ENTER("apply_event_and_update_pos");
|
long sql_delay= rli->get_sql_delay();
|
||||||
|
|
||||||
|
DBUG_ENTER("sql_delay_event");
|
||||||
|
mysql_mutex_assert_owner(&rli->data_lock);
|
||||||
|
DBUG_ASSERT(!rli->belongs_to_client());
|
||||||
|
|
||||||
|
int type= ev->get_type_code();
|
||||||
|
if (sql_delay && type != ROTATE_EVENT &&
|
||||||
|
type != FORMAT_DESCRIPTION_EVENT && type != START_EVENT_V3)
|
||||||
|
{
|
||||||
|
// The time when we should execute the event.
|
||||||
|
time_t sql_delay_end=
|
||||||
|
ev->when + rli->mi->clock_diff_with_master + sql_delay;
|
||||||
|
// The current time.
|
||||||
|
time_t now= my_time(0);
|
||||||
|
// The time we will have to sleep before executing the event.
|
||||||
|
unsigned long nap_time= 0;
|
||||||
|
if (sql_delay_end > now)
|
||||||
|
nap_time= sql_delay_end - now;
|
||||||
|
|
||||||
|
DBUG_PRINT("info", ("sql_delay= %lu "
|
||||||
|
"ev->when= %lu "
|
||||||
|
"rli->mi->clock_diff_with_master= %lu "
|
||||||
|
"now= %ld "
|
||||||
|
"sql_delay_end= %lu "
|
||||||
|
"nap_time= %ld",
|
||||||
|
sql_delay, (long)ev->when,
|
||||||
|
rli->mi->clock_diff_with_master,
|
||||||
|
(long)now, sql_delay_end, (long)nap_time));
|
||||||
|
|
||||||
|
if (sql_delay_end > now)
|
||||||
|
{
|
||||||
|
DBUG_PRINT("info", ("delaying replication event %lu secs",
|
||||||
|
nap_time));
|
||||||
|
rli->start_sql_delay(sql_delay_end);
|
||||||
|
mysql_mutex_unlock(&rli->data_lock);
|
||||||
|
DBUG_RETURN(slave_sleep(thd, nap_time, sql_slave_killed, rgi));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mysql_mutex_unlock(&rli->data_lock);
|
||||||
|
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
First half of apply_event_and_update_pos(), see below.
|
||||||
|
Setup some THD variables for applying the event.
|
||||||
|
|
||||||
|
Split out so that it can run with rli->data_lock held in non-parallel
|
||||||
|
replication, but without the mutex held in the parallel case.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
apply_event_and_update_pos_setup(Log_event* ev, THD* thd, rpl_group_info *rgi)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("apply_event_and_update_pos_setup");
|
||||||
|
|
||||||
DBUG_PRINT("exec_event",("%s(type_code: %d; server_id: %d)",
|
DBUG_PRINT("exec_event",("%s(type_code: %d; server_id: %d)",
|
||||||
ev->get_type_str(), ev->get_type_code(),
|
ev->get_type_str(), ev->get_type_code(),
|
||||||
@ -3450,13 +3525,23 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd,
|
|||||||
(ev->flags & LOG_EVENT_SKIP_REPLICATION_F ? OPTION_SKIP_REPLICATION : 0);
|
(ev->flags & LOG_EVENT_SKIP_REPLICATION_F ? OPTION_SKIP_REPLICATION : 0);
|
||||||
ev->thd = thd; // because up to this point, ev->thd == 0
|
ev->thd = thd; // because up to this point, ev->thd == 0
|
||||||
|
|
||||||
int reason= ev->shall_skip(rgi);
|
DBUG_RETURN(ev->shall_skip(rgi));
|
||||||
if (reason == Log_event::EVENT_SKIP_COUNT)
|
|
||||||
{
|
|
||||||
DBUG_ASSERT(rli->slave_skip_counter > 0);
|
|
||||||
rli->slave_skip_counter--;
|
|
||||||
}
|
}
|
||||||
mysql_mutex_unlock(&rli->data_lock);
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Second half of apply_event_and_update_pos(), see below.
|
||||||
|
|
||||||
|
Do the actual event apply (or skip), and position update.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
apply_event_and_update_pos_apply(Log_event* ev, THD* thd, rpl_group_info *rgi,
|
||||||
|
int reason)
|
||||||
|
{
|
||||||
|
int exec_res= 0;
|
||||||
|
Relay_log_info* rli= rgi->rli;
|
||||||
|
|
||||||
|
DBUG_ENTER("apply_event_and_update_pos_apply");
|
||||||
DBUG_EXECUTE_IF("inject_slave_sql_before_apply_event",
|
DBUG_EXECUTE_IF("inject_slave_sql_before_apply_event",
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(!debug_sync_set_action
|
DBUG_ASSERT(!debug_sync_set_action
|
||||||
@ -3503,16 +3588,16 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd,
|
|||||||
if (exec_res == 0)
|
if (exec_res == 0)
|
||||||
{
|
{
|
||||||
int error= ev->update_pos(rgi);
|
int error= ev->update_pos(rgi);
|
||||||
#ifdef HAVE_valgrind
|
#ifndef DBUG_OFF
|
||||||
if (!rli->is_fake)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
DBUG_PRINT("info", ("update_pos error = %d", error));
|
DBUG_PRINT("info", ("update_pos error = %d", error));
|
||||||
|
if (!rli->belongs_to_client())
|
||||||
|
{
|
||||||
DBUG_PRINT("info", ("group %llu %s", rli->group_relay_log_pos,
|
DBUG_PRINT("info", ("group %llu %s", rli->group_relay_log_pos,
|
||||||
rli->group_relay_log_name));
|
rli->group_relay_log_name));
|
||||||
DBUG_PRINT("info", ("event %llu %s", rli->event_relay_log_pos,
|
DBUG_PRINT("info", ("event %llu %s", rli->event_relay_log_pos,
|
||||||
rli->event_relay_log_name));
|
rli->event_relay_log_name));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
The update should not fail, so print an error message and
|
The update should not fail, so print an error message and
|
||||||
return an error code.
|
return an error code.
|
||||||
@ -3544,6 +3629,103 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Applies the given event and advances the relay log position.
|
||||||
|
|
||||||
|
This is needed by the sql thread to execute events from the binlog,
|
||||||
|
and by clients executing BINLOG statements. Conceptually, this
|
||||||
|
function does:
|
||||||
|
|
||||||
|
@code
|
||||||
|
ev->apply_event(rli);
|
||||||
|
ev->update_pos(rli);
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
It also does the following maintainance:
|
||||||
|
|
||||||
|
- Initializes the thread's server_id and time; and the event's
|
||||||
|
thread.
|
||||||
|
|
||||||
|
- If !rli->belongs_to_client() (i.e., if it belongs to the slave
|
||||||
|
sql thread instead of being used for executing BINLOG
|
||||||
|
statements), it does the following things: (1) skips events if it
|
||||||
|
is needed according to the server id or slave_skip_counter; (2)
|
||||||
|
unlocks rli->data_lock; (3) sleeps if required by 'CHANGE MASTER
|
||||||
|
TO MASTER_DELAY=X'; (4) maintains the running state of the sql
|
||||||
|
thread (rli->thread_state).
|
||||||
|
|
||||||
|
- 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.
|
||||||
|
|
||||||
|
@retval 1 Error calling ev->apply_event().
|
||||||
|
|
||||||
|
@retval 2 No error calling ev->apply_event(), but error calling
|
||||||
|
ev->update_pos().
|
||||||
|
|
||||||
|
This function is only used in non-parallel replication, where it is called
|
||||||
|
with rli->data_lock held; this lock is released during this function.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
apply_event_and_update_pos(Log_event* ev, THD* thd, rpl_group_info *rgi)
|
||||||
|
{
|
||||||
|
Relay_log_info* rli= rgi->rli;
|
||||||
|
mysql_mutex_assert_owner(&rli->data_lock);
|
||||||
|
int reason= apply_event_and_update_pos_setup(ev, thd, rgi);
|
||||||
|
if (reason == Log_event::EVENT_SKIP_COUNT)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(rli->slave_skip_counter > 0);
|
||||||
|
rli->slave_skip_counter--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reason == Log_event::EVENT_SKIP_NOT)
|
||||||
|
{
|
||||||
|
// Sleeps if needed, and unlocks rli->data_lock.
|
||||||
|
if (sql_delay_event(ev, thd, rgi))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mysql_mutex_unlock(&rli->data_lock);
|
||||||
|
|
||||||
|
return apply_event_and_update_pos_apply(ev, thd, rgi, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
The version of above apply_event_and_update_pos() used in parallel
|
||||||
|
replication. Unlike the non-parallel case, this function is called without
|
||||||
|
rli->data_lock held.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
apply_event_and_update_pos_for_parallel(Log_event* ev, THD* thd,
|
||||||
|
rpl_group_info *rgi)
|
||||||
|
{
|
||||||
|
Relay_log_info* rli= rgi->rli;
|
||||||
|
mysql_mutex_assert_not_owner(&rli->data_lock);
|
||||||
|
int reason= apply_event_and_update_pos_setup(ev, thd, rgi);
|
||||||
|
/*
|
||||||
|
In parallel replication, sql_slave_skip_counter is handled in the SQL
|
||||||
|
driver thread, so 23 should never see EVENT_SKIP_COUNT here.
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(reason != Log_event::EVENT_SKIP_COUNT);
|
||||||
|
/*
|
||||||
|
Calling sql_delay_event() was handled in the SQL driver thread when
|
||||||
|
doing parallel replication.
|
||||||
|
*/
|
||||||
|
return apply_event_and_update_pos_apply(ev, thd, rgi, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Keep the relay log transaction state up to date.
|
Keep the relay log transaction state up to date.
|
||||||
|
|
||||||
@ -3619,7 +3801,8 @@ inline void update_state_of_relay_log(Relay_log_info *rli, Log_event *ev)
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Top-level function for executing the next event from the relay log.
|
Top-level function for executing the next event in the relay log.
|
||||||
|
This is called from the SQL thread.
|
||||||
|
|
||||||
This function reads the event from the relay log, executes it, and
|
This function reads the event from the relay log, executes it, and
|
||||||
advances the relay log position. It also handles errors, etc.
|
advances the relay log position. It also handles errors, etc.
|
||||||
@ -3794,7 +3977,7 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli,
|
|||||||
serial_rgi->future_event_relay_log_pos= rli->future_event_relay_log_pos;
|
serial_rgi->future_event_relay_log_pos= rli->future_event_relay_log_pos;
|
||||||
serial_rgi->event_relay_log_name= rli->event_relay_log_name;
|
serial_rgi->event_relay_log_name= rli->event_relay_log_name;
|
||||||
serial_rgi->event_relay_log_pos= rli->event_relay_log_pos;
|
serial_rgi->event_relay_log_pos= rli->event_relay_log_pos;
|
||||||
exec_res= apply_event_and_update_pos(ev, thd, serial_rgi, NULL);
|
exec_res= apply_event_and_update_pos(ev, thd, serial_rgi);
|
||||||
|
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
WSREP_DEBUG("apply_event_and_update_pos() result: %d", exec_res);
|
WSREP_DEBUG("apply_event_and_update_pos() result: %d", exec_res);
|
||||||
@ -4164,8 +4347,10 @@ connected:
|
|||||||
};);
|
};);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO: the assignment below should be under mutex (5.0)
|
mysql_mutex_lock(&mi->run_lock);
|
||||||
mi->slave_running= MYSQL_SLAVE_RUN_CONNECT;
|
mi->slave_running= MYSQL_SLAVE_RUN_CONNECT;
|
||||||
|
mysql_mutex_unlock(&mi->run_lock);
|
||||||
|
|
||||||
thd->slave_net = &mysql->net;
|
thd->slave_net = &mysql->net;
|
||||||
THD_STAGE_INFO(thd, stage_checking_master_version);
|
THD_STAGE_INFO(thd, stage_checking_master_version);
|
||||||
ret= get_master_version_and_clock(mysql, mi);
|
ret= get_master_version_and_clock(mysql, mi);
|
||||||
@ -4928,7 +5113,7 @@ pthread_handler_t handle_slave_sql(void *arg)
|
|||||||
{
|
{
|
||||||
ulong domain_count;
|
ulong domain_count;
|
||||||
|
|
||||||
flush_relay_log_info(rli);
|
rli->flush();
|
||||||
if (mi->using_parallel())
|
if (mi->using_parallel())
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -6516,75 +6701,6 @@ MYSQL *rpl_connect_master(MYSQL *mysql)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
Store the file and position where the execute-slave thread are in the
|
|
||||||
relay log.
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
flush_relay_log_info()
|
|
||||||
rli Relay log information
|
|
||||||
|
|
||||||
NOTES
|
|
||||||
- As this is only called by the slave thread or on STOP SLAVE, with the
|
|
||||||
log_lock grabbed and the slave thread stopped, we don't need to have
|
|
||||||
a lock here.
|
|
||||||
- If there is an active transaction, then we don't update the position
|
|
||||||
in the relay log. This is to ensure that we re-execute statements
|
|
||||||
if we die in the middle of an transaction that was rolled back.
|
|
||||||
- As a transaction never spans binary logs, we don't have to handle the
|
|
||||||
case where we do a relay-log-rotation in the middle of the transaction.
|
|
||||||
If this would not be the case, we would have to ensure that we
|
|
||||||
don't delete the relay log file where the transaction started when
|
|
||||||
we switch to a new relay log file.
|
|
||||||
|
|
||||||
TODO
|
|
||||||
- Change the log file information to a binary format to avoid calling
|
|
||||||
longlong2str.
|
|
||||||
|
|
||||||
RETURN VALUES
|
|
||||||
0 ok
|
|
||||||
1 write error
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool flush_relay_log_info(Relay_log_info* rli)
|
|
||||||
{
|
|
||||||
bool error=0;
|
|
||||||
DBUG_ENTER("flush_relay_log_info");
|
|
||||||
|
|
||||||
if (unlikely(rli->no_storage))
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
|
|
||||||
IO_CACHE *file = &rli->info_file;
|
|
||||||
char buff[FN_REFLEN*2+22*2+4], *pos;
|
|
||||||
|
|
||||||
my_b_seek(file, 0L);
|
|
||||||
pos=strmov(buff, rli->group_relay_log_name);
|
|
||||||
*pos++='\n';
|
|
||||||
pos= longlong10_to_str(rli->group_relay_log_pos, pos, 10);
|
|
||||||
*pos++='\n';
|
|
||||||
pos=strmov(pos, rli->group_master_log_name);
|
|
||||||
*pos++='\n';
|
|
||||||
pos=longlong10_to_str(rli->group_master_log_pos, pos, 10);
|
|
||||||
*pos='\n';
|
|
||||||
if (my_b_write(file, (uchar*) buff, (size_t) (pos-buff)+1))
|
|
||||||
error=1;
|
|
||||||
if (flush_io_cache(file))
|
|
||||||
error=1;
|
|
||||||
if (sync_relayloginfo_period &&
|
|
||||||
!error &&
|
|
||||||
++(rli->sync_counter) >= sync_relayloginfo_period)
|
|
||||||
{
|
|
||||||
if (my_sync(rli->info_fd, MYF(MY_WME)))
|
|
||||||
error=1;
|
|
||||||
rli->sync_counter= 0;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
Flushing the relay log is done by the slave I/O thread
|
|
||||||
or by the user on STOP SLAVE.
|
|
||||||
*/
|
|
||||||
DBUG_RETURN(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Called when we notice that the current "hot" log got rotated under our feet.
|
Called when we notice that the current "hot" log got rotated under our feet.
|
||||||
@ -6941,7 +7057,7 @@ static Log_event* next_event(rpl_group_info *rgi, ulonglong *event_size)
|
|||||||
}
|
}
|
||||||
rli->event_relay_log_pos = BIN_LOG_HEADER_SIZE;
|
rli->event_relay_log_pos = BIN_LOG_HEADER_SIZE;
|
||||||
strmake_buf(rli->event_relay_log_name,rli->linfo.log_file_name);
|
strmake_buf(rli->event_relay_log_name,rli->linfo.log_file_name);
|
||||||
flush_relay_log_info(rli);
|
rli->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
25
sql/slave.h
25
sql/slave.h
@ -17,6 +17,14 @@
|
|||||||
#ifndef SLAVE_H
|
#ifndef SLAVE_H
|
||||||
#define SLAVE_H
|
#define SLAVE_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
MASTER_DELAY can be at most (1 << 31) - 1.
|
||||||
|
*/
|
||||||
|
#define MASTER_DELAY_MAX (0x7FFFFFFF)
|
||||||
|
#if INT_MAX < 0x7FFFFFFF
|
||||||
|
#error "don't support platforms where INT_MAX < 0x7FFFFFFF"
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@defgroup Replication Replication
|
@defgroup Replication Replication
|
||||||
@{
|
@{
|
||||||
@ -102,12 +110,14 @@ int init_dynarray_intvar_from_file(DYNAMIC_ARRAY* arr, IO_CACHE* f);
|
|||||||
|
|
||||||
In Master_info: run_lock, data_lock
|
In Master_info: run_lock, data_lock
|
||||||
run_lock protects all information about the run state: slave_running, thd
|
run_lock protects all information about the run state: slave_running, thd
|
||||||
and the existence of the I/O thread to stop/start it, you need this mutex).
|
and the existence of the I/O thread (to stop/start it, you need this mutex).
|
||||||
data_lock protects some moving members of the struct: counters (log name,
|
data_lock protects some moving members of the struct: counters (log name,
|
||||||
position) and relay log (MYSQL_BIN_LOG object).
|
position) and relay log (MYSQL_BIN_LOG object).
|
||||||
|
|
||||||
In Relay_log_info: run_lock, data_lock
|
In Relay_log_info: run_lock, data_lock
|
||||||
see Master_info
|
see Master_info
|
||||||
|
However, note that run_lock does not protect
|
||||||
|
Relay_log_info.run_state; that is protected by data_lock.
|
||||||
|
|
||||||
Order of acquisition: if you want to have LOCK_active_mi and a run_lock, you
|
Order of acquisition: if you want to have LOCK_active_mi and a run_lock, you
|
||||||
must acquire LOCK_active_mi first.
|
must acquire LOCK_active_mi first.
|
||||||
@ -173,7 +183,6 @@ extern const char *relay_log_basename;
|
|||||||
int init_slave();
|
int init_slave();
|
||||||
int init_recovery(Master_info* mi, const char** errmsg);
|
int init_recovery(Master_info* mi, const char** errmsg);
|
||||||
void init_slave_skip_errors(const char* arg);
|
void init_slave_skip_errors(const char* arg);
|
||||||
bool flush_relay_log_info(Relay_log_info* rli);
|
|
||||||
int register_slave_on_master(MYSQL* mysql);
|
int register_slave_on_master(MYSQL* mysql);
|
||||||
int terminate_slave_threads(Master_info* mi, int thread_mask,
|
int terminate_slave_threads(Master_info* mi, int thread_mask,
|
||||||
bool skip_lock = 0);
|
bool skip_lock = 0);
|
||||||
@ -242,9 +251,17 @@ void set_slave_thread_options(THD* thd);
|
|||||||
void set_slave_thread_default_charset(THD *thd, rpl_group_info *rgi);
|
void set_slave_thread_default_charset(THD *thd, rpl_group_info *rgi);
|
||||||
int rotate_relay_log(Master_info* mi);
|
int rotate_relay_log(Master_info* mi);
|
||||||
int has_temporary_error(THD *thd);
|
int has_temporary_error(THD *thd);
|
||||||
|
int sql_delay_event(Log_event *ev, THD *thd, rpl_group_info *rgi);
|
||||||
int apply_event_and_update_pos(Log_event* ev, THD* thd,
|
int apply_event_and_update_pos(Log_event* ev, THD* thd,
|
||||||
struct rpl_group_info *rgi,
|
struct rpl_group_info *rgi);
|
||||||
rpl_parallel_thread *rpt);
|
int apply_event_and_update_pos_for_parallel(Log_event* ev, THD* thd,
|
||||||
|
struct rpl_group_info *rgi);
|
||||||
|
|
||||||
|
int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
|
||||||
|
int init_floatvar_from_file(float* var, IO_CACHE* f, float default_val);
|
||||||
|
int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
|
||||||
|
const char *default_val);
|
||||||
|
int init_dynarray_intvar_from_file(DYNAMIC_ARRAY* arr, IO_CACHE* f);
|
||||||
|
|
||||||
pthread_handler_t handle_slave_io(void *arg);
|
pthread_handler_t handle_slave_io(void *arg);
|
||||||
void slave_output_error_info(rpl_group_info *rgi, THD *thd);
|
void slave_output_error_info(rpl_group_info *rgi, THD *thd);
|
||||||
|
@ -17,18 +17,99 @@
|
|||||||
#include <my_global.h>
|
#include <my_global.h>
|
||||||
#include "sql_priv.h"
|
#include "sql_priv.h"
|
||||||
#include "sql_binlog.h"
|
#include "sql_binlog.h"
|
||||||
#include "sql_parse.h" // check_global_access
|
#include "sql_parse.h"
|
||||||
#include "sql_acl.h" // *_ACL
|
#include "sql_acl.h"
|
||||||
#include "rpl_rli.h"
|
#include "rpl_rli.h"
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
#include "slave.h" // apply_event_and_update_pos
|
#include "slave.h"
|
||||||
#include "log_event.h" // Format_description_log_event,
|
#include "log_event.h"
|
||||||
// EVENT_LEN_OFFSET,
|
|
||||||
// EVENT_TYPE_OFFSET,
|
|
||||||
// FORMAT_DESCRIPTION_LOG_EVENT,
|
/**
|
||||||
// START_EVENT_V3,
|
Check if the event type is allowed in a BINLOG statement.
|
||||||
// Log_event_type,
|
|
||||||
// Log_event
|
@retval 0 if the event type is ok.
|
||||||
|
@retval 1 if the event type is not ok.
|
||||||
|
*/
|
||||||
|
static int check_event_type(int type, Relay_log_info *rli)
|
||||||
|
{
|
||||||
|
Format_description_log_event *fd_event=
|
||||||
|
rli->relay_log.description_event_for_exec;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Convert event type id of certain old versions (see comment in
|
||||||
|
Format_description_log_event::Format_description_log_event(char*,...)).
|
||||||
|
*/
|
||||||
|
if (fd_event && fd_event->event_type_permutation)
|
||||||
|
{
|
||||||
|
IF_DBUG({
|
||||||
|
int new_type= fd_event->event_type_permutation[type];
|
||||||
|
DBUG_PRINT("info",
|
||||||
|
("converting event type %d to %d (%s)",
|
||||||
|
type, new_type,
|
||||||
|
Log_event::get_type_str((Log_event_type)new_type)));
|
||||||
|
},
|
||||||
|
(void)0);
|
||||||
|
type= fd_event->event_type_permutation[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case START_EVENT_V3:
|
||||||
|
case FORMAT_DESCRIPTION_EVENT:
|
||||||
|
/*
|
||||||
|
We need a preliminary FD event in order to parse the FD event,
|
||||||
|
if we don't already have one.
|
||||||
|
*/
|
||||||
|
if (!fd_event)
|
||||||
|
if (!(rli->relay_log.description_event_for_exec=
|
||||||
|
new Format_description_log_event(4)))
|
||||||
|
{
|
||||||
|
my_error(ER_OUTOFMEMORY, MYF(0), 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* It is always allowed to execute FD events. */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case TABLE_MAP_EVENT:
|
||||||
|
case WRITE_ROWS_EVENT_V1:
|
||||||
|
case UPDATE_ROWS_EVENT_V1:
|
||||||
|
case DELETE_ROWS_EVENT_V1:
|
||||||
|
case WRITE_ROWS_EVENT:
|
||||||
|
case UPDATE_ROWS_EVENT:
|
||||||
|
case DELETE_ROWS_EVENT:
|
||||||
|
case PRE_GA_WRITE_ROWS_EVENT:
|
||||||
|
case PRE_GA_UPDATE_ROWS_EVENT:
|
||||||
|
case PRE_GA_DELETE_ROWS_EVENT:
|
||||||
|
/*
|
||||||
|
Row events are only allowed if a Format_description_event has
|
||||||
|
already been seen.
|
||||||
|
*/
|
||||||
|
if (fd_event)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
my_error(ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT,
|
||||||
|
MYF(0), Log_event::get_type_str((Log_event_type)type));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
It is not meaningful to execute other events than row-events and
|
||||||
|
FD events. It would even be dangerous to execute Stop_log_event
|
||||||
|
and Rotate_log_event since they call Relay_log_info::flush(), which
|
||||||
|
is not allowed to call by other threads than the slave SQL
|
||||||
|
thread when the slave SQL thread is running.
|
||||||
|
*/
|
||||||
|
my_error(ER_ONLY_FD_AND_RBR_EVENTS_ALLOWED_IN_BINLOG_STATEMENT,
|
||||||
|
MYF(0), Log_event::get_type_str((Log_event_type)type));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Execute a BINLOG statement.
|
Execute a BINLOG statement.
|
||||||
|
|
||||||
@ -73,31 +154,13 @@ void mysql_client_binlog_statement(THD* thd)
|
|||||||
Allocation
|
Allocation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
If we do not have a Format_description_event, we create a dummy
|
|
||||||
one here. In this case, the first event we read must be a
|
|
||||||
Format_description_event.
|
|
||||||
*/
|
|
||||||
my_bool have_fd_event= TRUE;
|
|
||||||
int err;
|
int err;
|
||||||
Relay_log_info *rli;
|
Relay_log_info *rli;
|
||||||
rpl_group_info *rgi;
|
rpl_group_info *rgi;
|
||||||
|
|
||||||
rli= thd->rli_fake;
|
rli= thd->rli_fake;
|
||||||
if (!rli)
|
if (!rli && (rli= thd->rli_fake= new Relay_log_info(FALSE)))
|
||||||
{
|
rli->sql_driver_thd= thd;
|
||||||
rli= thd->rli_fake= new Relay_log_info(FALSE);
|
|
||||||
#ifdef HAVE_valgrind
|
|
||||||
rli->is_fake= TRUE;
|
|
||||||
#endif
|
|
||||||
have_fd_event= FALSE;
|
|
||||||
}
|
|
||||||
if (rli && !rli->relay_log.description_event_for_exec)
|
|
||||||
{
|
|
||||||
rli->relay_log.description_event_for_exec=
|
|
||||||
new Format_description_log_event(4);
|
|
||||||
have_fd_event= FALSE;
|
|
||||||
}
|
|
||||||
if (!(rgi= thd->rgi_fake))
|
if (!(rgi= thd->rgi_fake))
|
||||||
rgi= thd->rgi_fake= new rpl_group_info(rli);
|
rgi= thd->rgi_fake= new rpl_group_info(rli);
|
||||||
rgi->thd= thd;
|
rgi->thd= thd;
|
||||||
@ -109,16 +172,13 @@ void mysql_client_binlog_statement(THD* thd)
|
|||||||
/*
|
/*
|
||||||
Out of memory check
|
Out of memory check
|
||||||
*/
|
*/
|
||||||
if (!(rli &&
|
if (!(rli && buf))
|
||||||
rli->relay_log.description_event_for_exec &&
|
|
||||||
buf))
|
|
||||||
{
|
{
|
||||||
my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), 1); /* needed 1 bytes */
|
my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), 1); /* needed 1 bytes */
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
rli->sql_driver_thd= thd;
|
DBUG_ASSERT(rli->belongs_to_client());
|
||||||
rli->no_storage= TRUE;
|
|
||||||
|
|
||||||
for (char const *strptr= thd->lex->comment.str ;
|
for (char const *strptr= thd->lex->comment.str ;
|
||||||
strptr < thd->lex->comment.str + thd->lex->comment.length ; )
|
strptr < thd->lex->comment.str + thd->lex->comment.length ; )
|
||||||
@ -185,23 +245,8 @@ void mysql_client_binlog_statement(THD* thd)
|
|||||||
DBUG_PRINT("info", ("event_len=%lu, bytes_decoded=%d",
|
DBUG_PRINT("info", ("event_len=%lu, bytes_decoded=%d",
|
||||||
event_len, bytes_decoded));
|
event_len, bytes_decoded));
|
||||||
|
|
||||||
/*
|
if (check_event_type(bufptr[EVENT_TYPE_OFFSET], rli))
|
||||||
If we have not seen any Format_description_event, then we must
|
|
||||||
see one; it is the only statement that can be read in base64
|
|
||||||
without a prior Format_description_event.
|
|
||||||
*/
|
|
||||||
if (!have_fd_event)
|
|
||||||
{
|
|
||||||
int type = (uchar)bufptr[EVENT_TYPE_OFFSET];
|
|
||||||
if (type == FORMAT_DESCRIPTION_EVENT || type == START_EVENT_V3)
|
|
||||||
have_fd_event= TRUE;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
my_error(ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT,
|
|
||||||
MYF(0), Log_event::get_type_str((Log_event_type)type));
|
|
||||||
goto end;
|
goto end;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ev= Log_event::read_log_event(bufptr, event_len, &error,
|
ev= Log_event::read_log_event(bufptr, event_len, &error,
|
||||||
rli->relay_log.description_event_for_exec,
|
rli->relay_log.description_event_for_exec,
|
||||||
@ -212,7 +257,7 @@ void mysql_client_binlog_statement(THD* thd)
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
This could actually be an out-of-memory, but it is more likely
|
This could actually be an out-of-memory, but it is more likely
|
||||||
causes by a bad statement
|
caused by a bad statement
|
||||||
*/
|
*/
|
||||||
my_error(ER_SYNTAX_ERROR, MYF(0));
|
my_error(ER_SYNTAX_ERROR, MYF(0));
|
||||||
goto end;
|
goto end;
|
||||||
|
@ -246,11 +246,12 @@ struct LEX_MASTER_INFO
|
|||||||
ulong server_id;
|
ulong server_id;
|
||||||
uint port, connect_retry;
|
uint port, connect_retry;
|
||||||
float heartbeat_period;
|
float heartbeat_period;
|
||||||
|
int sql_delay;
|
||||||
/*
|
/*
|
||||||
Enum is used for making it possible to detect if the user
|
Enum is used for making it possible to detect if the user
|
||||||
changed variable or if it should be left at old value
|
changed variable or if it should be left at old value
|
||||||
*/
|
*/
|
||||||
enum {LEX_MI_UNCHANGED, LEX_MI_DISABLE, LEX_MI_ENABLE}
|
enum {LEX_MI_UNCHANGED= 0, LEX_MI_DISABLE, LEX_MI_ENABLE}
|
||||||
ssl, ssl_verify_server_cert, heartbeat_opt, repl_ignore_server_ids_opt,
|
ssl, ssl_verify_server_cert, heartbeat_opt, repl_ignore_server_ids_opt,
|
||||||
repl_do_domain_ids_opt, repl_ignore_domain_ids_opt;
|
repl_do_domain_ids_opt, repl_ignore_domain_ids_opt;
|
||||||
enum {
|
enum {
|
||||||
@ -266,6 +267,7 @@ struct LEX_MASTER_INFO
|
|||||||
sizeof(ulong), 0, 16, MYF(0));
|
sizeof(ulong), 0, 16, MYF(0));
|
||||||
my_init_dynamic_array(&repl_ignore_domain_ids,
|
my_init_dynamic_array(&repl_ignore_domain_ids,
|
||||||
sizeof(ulong), 0, 16, MYF(0));
|
sizeof(ulong), 0, 16, MYF(0));
|
||||||
|
sql_delay= -1;
|
||||||
}
|
}
|
||||||
void reset(bool is_change_master)
|
void reset(bool is_change_master)
|
||||||
{
|
{
|
||||||
@ -286,6 +288,7 @@ struct LEX_MASTER_INFO
|
|||||||
repl_ignore_domain_ids_opt= LEX_MI_UNCHANGED;
|
repl_ignore_domain_ids_opt= LEX_MI_UNCHANGED;
|
||||||
gtid_pos_str= null_lex_str;
|
gtid_pos_str= null_lex_str;
|
||||||
use_gtid_opt= LEX_GTID_UNCHANGED;
|
use_gtid_opt= LEX_GTID_UNCHANGED;
|
||||||
|
sql_delay= -1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -495,7 +495,7 @@ static enum enum_binlog_checksum_alg get_binlog_checksum_value_at_connect(THD *
|
|||||||
|
|
||||||
TODO
|
TODO
|
||||||
- Inform the slave threads that they should sync the position
|
- Inform the slave threads that they should sync the position
|
||||||
in the binary log file with flush_relay_log_info.
|
in the binary log file with Relay_log_info::flush().
|
||||||
Now they sync is done for next read.
|
Now they sync is done for next read.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -3304,6 +3304,7 @@ int reset_slave(THD *thd, Master_info* mi)
|
|||||||
mi->clear_error();
|
mi->clear_error();
|
||||||
mi->rli.clear_error();
|
mi->rli.clear_error();
|
||||||
mi->rli.clear_until_condition();
|
mi->rli.clear_until_condition();
|
||||||
|
mi->rli.clear_sql_delay();
|
||||||
mi->rli.slave_skip_counter= 0;
|
mi->rli.slave_skip_counter= 0;
|
||||||
|
|
||||||
// close master_info_file, relay_log_info_file, set mi->inited=rli->inited=0
|
// close master_info_file, relay_log_info_file, set mi->inited=rli->inited=0
|
||||||
@ -3613,6 +3614,9 @@ bool change_master(THD* thd, Master_info* mi, bool *master_info_added)
|
|||||||
if (lex_mi->ssl != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
|
if (lex_mi->ssl != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
|
||||||
mi->ssl= (lex_mi->ssl == LEX_MASTER_INFO::LEX_MI_ENABLE);
|
mi->ssl= (lex_mi->ssl == LEX_MASTER_INFO::LEX_MI_ENABLE);
|
||||||
|
|
||||||
|
if (lex_mi->sql_delay != -1)
|
||||||
|
mi->rli.set_sql_delay(lex_mi->sql_delay);
|
||||||
|
|
||||||
if (lex_mi->ssl_verify_server_cert != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
|
if (lex_mi->ssl_verify_server_cert != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
|
||||||
mi->ssl_verify_server_cert=
|
mi->ssl_verify_server_cert=
|
||||||
(lex_mi->ssl_verify_server_cert == LEX_MASTER_INFO::LEX_MI_ENABLE);
|
(lex_mi->ssl_verify_server_cert == LEX_MASTER_INFO::LEX_MI_ENABLE);
|
||||||
@ -3797,7 +3801,7 @@ bool change_master(THD* thd, Master_info* mi, bool *master_info_added)
|
|||||||
in-memory value at restart (thus causing errors, as the old relay log does
|
in-memory value at restart (thus causing errors, as the old relay log does
|
||||||
not exist anymore).
|
not exist anymore).
|
||||||
*/
|
*/
|
||||||
flush_relay_log_info(&mi->rli);
|
mi->rli.flush();
|
||||||
mysql_cond_broadcast(&mi->data_cond);
|
mysql_cond_broadcast(&mi->data_cond);
|
||||||
mysql_mutex_unlock(&mi->rli.data_lock);
|
mysql_mutex_unlock(&mi->rli.data_lock);
|
||||||
|
|
||||||
|
@ -1359,6 +1359,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
|||||||
%token LOOP_SYM
|
%token LOOP_SYM
|
||||||
%token LOW_PRIORITY
|
%token LOW_PRIORITY
|
||||||
%token MASTER_CONNECT_RETRY_SYM
|
%token MASTER_CONNECT_RETRY_SYM
|
||||||
|
%token MASTER_DELAY_SYM
|
||||||
%token MASTER_GTID_POS_SYM
|
%token MASTER_GTID_POS_SYM
|
||||||
%token MASTER_HOST_SYM
|
%token MASTER_HOST_SYM
|
||||||
%token MASTER_LOG_FILE_SYM
|
%token MASTER_LOG_FILE_SYM
|
||||||
@ -2338,6 +2339,16 @@ master_def:
|
|||||||
{
|
{
|
||||||
Lex->mi.connect_retry = $3;
|
Lex->mi.connect_retry = $3;
|
||||||
}
|
}
|
||||||
|
| MASTER_DELAY_SYM '=' 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.sql_delay = $3;
|
||||||
|
}
|
||||||
| MASTER_SSL_SYM '=' ulong_num
|
| MASTER_SSL_SYM '=' ulong_num
|
||||||
{
|
{
|
||||||
Lex->mi.ssl= $3 ?
|
Lex->mi.ssl= $3 ?
|
||||||
@ -7850,6 +7861,7 @@ slave:
|
|||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
lex->sql_command = SQLCOM_SLAVE_ALL_START;
|
lex->sql_command = SQLCOM_SLAVE_ALL_START;
|
||||||
lex->type = 0;
|
lex->type = 0;
|
||||||
|
/* If you change this code don't forget to update STOP SLAVE too */
|
||||||
}
|
}
|
||||||
{}
|
{}
|
||||||
| STOP_SYM SLAVE optional_connection_name slave_thread_opts
|
| STOP_SYM SLAVE optional_connection_name slave_thread_opts
|
||||||
@ -14744,6 +14756,7 @@ keyword_sp:
|
|||||||
| MASTER_PASSWORD_SYM {}
|
| MASTER_PASSWORD_SYM {}
|
||||||
| MASTER_SERVER_ID_SYM {}
|
| MASTER_SERVER_ID_SYM {}
|
||||||
| MASTER_CONNECT_RETRY_SYM {}
|
| MASTER_CONNECT_RETRY_SYM {}
|
||||||
|
| MASTER_DELAY_SYM {}
|
||||||
| MASTER_SSL_SYM {}
|
| MASTER_SSL_SYM {}
|
||||||
| MASTER_SSL_CA_SYM {}
|
| MASTER_SSL_CA_SYM {}
|
||||||
| MASTER_SSL_CAPATH_SYM {}
|
| MASTER_SSL_CAPATH_SYM {}
|
||||||
|
@ -97,7 +97,6 @@ static rpl_group_info* wsrep_relay_group_init(const char* log_fname)
|
|||||||
{
|
{
|
||||||
Relay_log_info* rli= new Relay_log_info(false);
|
Relay_log_info* rli= new Relay_log_info(false);
|
||||||
|
|
||||||
rli->no_storage= true;
|
|
||||||
if (!rli->relay_log.description_event_for_exec)
|
if (!rli->relay_log.description_event_for_exec)
|
||||||
{
|
{
|
||||||
rli->relay_log.description_event_for_exec=
|
rli->relay_log.description_event_for_exec=
|
||||||
|
@ -461,7 +461,7 @@ static void test_prepare_simple()
|
|||||||
strmov(query, "SHOW SLAVE STATUS");
|
strmov(query, "SHOW SLAVE STATUS");
|
||||||
stmt= mysql_simple_prepare(mysql, query);
|
stmt= mysql_simple_prepare(mysql, query);
|
||||||
check_stmt(stmt);
|
check_stmt(stmt);
|
||||||
DIE_UNLESS(mysql_stmt_field_count(stmt) == 47);
|
DIE_UNLESS(mysql_stmt_field_count(stmt) == 50);
|
||||||
mysql_stmt_close(stmt);
|
mysql_stmt_close(stmt);
|
||||||
|
|
||||||
/* show master status */
|
/* show master status */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user