#At file:///C:/source/bzr/mysql-6.0-bug-39780/ based on revid:charles.bell@stripped
2764 Chuck Bell 2009-02-09
BUG#39780 Allow restore to skip gap event during restore on master
This patch adds a new option to the restore command: skip_gap_event.
It is used to skip writing the incident event when a restore is
run on a master in an active replication topology (gap event).
modified:
mysql-test/suite/rpl/r/rpl_backup.result
mysql-test/suite/rpl/t/rpl_backup.test
sql/backup/backup_kernel.h
sql/backup/kernel.cc
sql/lex.h
sql/sql_parse.cc
sql/sql_yacc.yy
per-file messages:
mysql-test/suite/rpl/r/rpl_backup.result
Corrected result file.
mysql-test/suite/rpl/t/rpl_backup.test
Added test case for skipping gap event.
Minor refactoring of comments.
sql/backup/backup_kernel.h
Added parameter to pass on value of skip_gap_event check.
sql/backup/kernel.cc
Added parameter to pass on the result of the skip_gap_event check.
Added code to skip gap event when triggered.
sql/lex.h
Added new symbol.
sql/sql_parse.cc
Added code to pass the skip_gap_event signal to the proper locations.
Simplified option check code.
sql/sql_yacc.yy
Extended restore syntax to include new option.
=== modified file 'mysql-test/suite/rpl/r/rpl_backup.result'
--- a/mysql-test/suite/rpl/r/rpl_backup.result 2009-02-01 19:17:09 +0000
+++ b/mysql-test/suite/rpl/r/rpl_backup.result 2009-02-09 22:23:14 +0000
@@ -4,45 +4,49 @@ reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
-Create some data...
+# Connecting to master...
+# Create some data...
CREATE DATABASE rpl_backup;
CREATE TABLE rpl_backup.t1 (a int);
INSERT INTO rpl_backup.t1 VALUES (1), (2), (3), (4), (5);
-Remove all entries in the backup logs.
+# Remove all entries in the backup logs.
FLUSH BACKUP LOGS;
PURGE BACKUP LOGS;
-Get slave's datadir.
-Remove all entries in the backup logs.
+# Connecting to slave...
+# Get slave's datadir.
+# Remove all entries in the backup logs.
FLUSH BACKUP LOGS;
PURGE BACKUP LOGS;
-Get master's binlog position from the slave before backup.
-Get master's datadir.
-Get master's binlog position before backup.
+# Get master's binlog position from the slave before backup.
+# Connecting to master...
+# Get master's datadir.
+# Get master's binlog position before backup.
SET SESSION debug="+d,set_backup_id";
-Backup_id = 500.
+# Backup_id = 500.
BACKUP DATABASE rpl_backup TO 'rpl_bup_m1.bak';
backup_id
500
SET SESSION debug="-d";
-Show any events issued as a result of backup.
-Note: There should be none!
+# Show any events issued as a result of backup.
+# Note: There should be none!
Log_name Pos Event_type Server_id End_log_pos Info
-Verify backup run on master does not advance binlog pos.
-Get master's binlog position after backup.
-Compare the before position of the master's binlog to
-the after position of the master's binlog. The result
-should be 0.
+# Verify backup run on master does not advance binlog pos.
+# Get master's binlog position after backup.
+# Compare the before position of the master's binlog to
+# the after position of the master's binlog. The result
+# should be 0.
Delta
0
-Should have count(*) = 0.
+# Connecting to slave...
+# Should have count(*) = 0.
SELECT count(*) FROM mysql.backup_history;
count(*)
0
-Verify backup run on master does not advance binlog pos.
-Get master's binlog position on the slave after backup.
-Compare the before position of the master's binlog to
-the after position of the slave's binlog as shown on
-on the slave. The result should be 0.
+# Verify backup run on master does not advance binlog pos.
+# Get master's binlog position on the slave after backup.
+# Compare the before position of the master's binlog to
+# the after position of the slave's binlog as shown on
+# on the slave. The result should be 0.
Delta
0
SHOW SLAVE STATUS;
@@ -86,22 +90,26 @@ Last_SQL_Errno 0
Last_SQL_Error
Replicate_Ignore_Server_Ids
Master_Server_Id 1
-Ensure replication is still working...
-Cleanup from last error on master and slave.
+# Connecting to master...
+# Ensure replication is still working...
+# Cleanup from last error on master and slave.
DELETE FROM rpl_backup.t1;
INSERT INTO rpl_backup.t1 VALUES (11), (22), (33);
SELECT count(*) FROM rpl_backup.t1;
count(*)
3
+# Connecting to slave...
SELECT count(*) FROM rpl_backup.t1;
count(*)
3
-Cleanup backup logs.
+# Cleanup backup logs.
FLUSH BACKUP LOGS;
PURGE BACKUP LOGS;
-First, get master's binlog position and filename.
+# Connecting to master...
+# First, get master's binlog position and filename.
+# Connecting to slave...
SET SESSION debug="+d,set_backup_id";
-Backup_id = 600.
+# Backup_id = 600.
BACKUP DATABASE rpl_backup TO 'rpl_bup_s1.bak';
backup_id
600
@@ -147,50 +155,54 @@ Last_SQL_Errno 0
Last_SQL_Error
Replicate_Ignore_Server_Ids
Master_Server_Id 1
-Check saving of master's binlog information.
-Should have count(*) = 1.
+# Check saving of master's binlog information.
+# Should have count(*) = 1.
count(*)
1
-Should have count(*) = 1.
+# Should have count(*) = 1.
SELECT count(*) FROM mysql.backup_history;
count(*)
1
+# Connecting to master...
INSERT INTO rpl_backup.t1 VALUES (10), (20), (30);
-Backup_id = 501.
-BACKUP DATABASE rpl_backup TO 'rpl_bup_m2.bak';
+# Backup_id = 501.
+# BACKUP DATABASE rpl_backup TO 'rpl_bup_m2.bak';
backup_id
501
SELECT count(*) FROM rpl_backup.t1;
count(*)
6
+# Connecting to slave...
SELECT count(*) FROM rpl_backup.t1;
count(*)
6
-Make a backup for later use.
-Backup_id = 601.
+# Make a backup for later use.
+# Backup_id = 601.
BACKUP DATABASE rpl_backup TO 'rpl_bup_s2.bak';
backup_id
601
+# Connecting to master...
CREATE TABLE rpl_backup.t2 (b int);
INSERT INTO rpl_backup.t2 VALUES (888), (999);
-Get master's binlog position before restore.
-Backup_id = 502.
-RESTORE FROM 'rpl_bup_m2.bak';
+# Get master's binlog position before restore.
+# Backup_id = 502.
+# RESTORE FROM 'rpl_bup_m2.bak';
backup_id
502
-Show the incident event issued as a result of restore.
+# Show the incident event issued as a result of restore.
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Incident 1 # #2 (RESTORE_ON_MASTER)
master-bin.000001 # Rotate 1 # master-bin.000002;pos=4
-Showing tables on master.
+# Showing tables on master.
SHOW FULL TABLES FROM rpl_backup;
Tables_in_rpl_backup Table_type
t1 BASE TABLE
SELECT count(*) FROM rpl_backup.t1;
count(*)
6
-Check slave got everything up to incident event.
-Should be two rows: 888, 999.
+# Connecting to slave...
+# Check slave got everything up to incident event.
+# Should be two rows: 888, 999.
SELECT * FROM rpl_backup.t2 WHERE b > 800;
b
888
@@ -236,23 +248,23 @@ Last_SQL_Errno 1590
Last_SQL_Error The incident RESTORE_ON_MASTER occured on the master. Message: A restore operation was initiated on the master.
Replicate_Ignore_Server_Ids
Master_Server_Id 1
-Show the slave stopped with an error.
+# Show the slave stopped with an error.
Last_SQL_Error
The incident RESTORE_ON_MASTER occured on the master. Message: A restore operation was initiated on the master.
SET global sql_slave_skip_counter=1;
STOP SLAVE;
START SLAVE;
-Showing tables on slave.
+# Showing tables on slave.
SHOW FULL TABLES FROM rpl_backup;
Tables_in_rpl_backup Table_type
t1 BASE TABLE
t2 BASE TABLE
STOP SLAVE;
-Backup_id = 602.
-RESTORE_FROM 'rpl_bup_m2.bak';
+# Backup_id = 602.
+# RESTORE_FROM 'rpl_bup_m2.bak';
backup_id
602
-Showing databases on slave.
+# Showing databases on slave.
SHOW DATABASES LIKE 'rpl_backup%';
Database (rpl_backup%)
rpl_backup
@@ -260,21 +272,23 @@ SELECT count(*) FROM rpl_backup.t1;
count(*)
6
START SLAVE;
-Make a backup for later use.
-Backup_id = 603.
+# Make a backup for later use.
+# Backup_id = 603.
BACKUP DATABASE rpl_backup TO 'rpl_bup_s3.bak';
backup_id
603
-Test restore on slave while replication turned on.
+# Connecting to slave...
+# Test restore on slave while replication turned on.
RESTORE FROM 'rpl_bup_s1.bak' OVERWRITE;
ERROR HY000: A restore operation was attempted on a slave during replication. You must stop the slave prior to running a restore.
-Stop slave and restart after restore.
+# Stop slave and restart after restore.
STOP SLAVE;
RESTORE FROM 'rpl_bup_s3.bak' OVERWRITE;
backup_id
#
START SLAVE;
-Checking affect on replication.
+# Connecting to master...
+# Checking affect on replication.
INSERT INTO rpl_backup.t1 VALUES (44), (55), (66);
SELECT * FROM rpl_backup.t1 ORDER BY a;
a
@@ -287,6 +301,7 @@ a
44
55
66
+# Connecting to slave...
SELECT * FROM rpl_backup.t1 ORDER BY a;
a
10
@@ -298,50 +313,55 @@ a
44
55
66
-Stop replication and turn off binary log.
+# Connecting to slave...
+# Stop replication and turn off binary log.
STOP SLAVE;
+# Connecting to master...
SET @orig_sql_log_bin= @@sql_log_bin;
-Turn off binlog.
+# Turn off binlog.
SET @@sql_log_bin= 0;
SHOW VARIABLES LIKE '%log_bin';
Variable_name Value
log_bin ON
sql_log_bin OFF
-Backup_id = 503.
+# Backup_id = 503.
BACKUP DATABASE rpl_backup TO 'rpl_bup_m3.bak';
backup_id
503
-Turn on binlog;
+# Turn on binlog;
SET @@sql_log_bin= @orig_sql_log_bin;
SHOW VARIABLES LIKE '%log_bin';
Variable_name Value
log_bin ON
sql_log_bin ON
RESET MASTER;
-Get master's binlog position before restore.
-Backup_id = 504.
+# Get master's binlog position before restore.
+# Backup_id = 504.
RESTORE FROM 'rpl_bup_m3.bak' OVERWRITE;
backup_id
504
-Get master's binlog position after restore.
-Show the incident event issued as a result of restore.
+# Get master's binlog position after restore.
+# Show the incident event issued as a result of restore.
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Incident 1 # #2 (RESTORE_ON_MASTER)
master-bin.000001 # Rotate 1 # master-bin.000002;pos=4
-Compute the difference of the binlog positions.
-Result should be 0.
-Compare the before position of the master's binlog to
-the after position of the master's binlog. The result
-should be 0.
+# Compute the difference of the binlog positions.
+# Result should be 0.
+# Compare the before position of the master's binlog to
+# the after position of the master's binlog. The result
+# should be 0.
Delta
0
RESET MASTER;
+# Connecting to slave...
RESET SLAVE;
SET DEBUG_SYNC = 'reset';
+# Connecting to slave...
SET DEBUG_SYNC = 'before_restore_done SIGNAL restore_running WAIT_FOR proceed';
RESTORE FROM 'rpl_bup_s3.bak' OVERWRITE;
+# Connecting to slave...
SET DEBUG_SYNC = 'now WAIT_FOR restore_running';
-Try to start the slave while restore is running -- gets error.
+# Try to start the slave while restore is running -- gets error.
SLAVE START;
ERROR HY000: Cannot start slave. SLAVE START is blocked by RESTORE.
SET DEBUG_SYNC = 'now SIGNAL proceed';
@@ -386,10 +406,12 @@ Last_SQL_Errno 0
Last_SQL_Error
Replicate_Ignore_Server_Ids
Master_Server_Id 1
-Restore is now complete.
+# Connecting to slave...
+# Restore is now complete.
backup_id
#
SET DEBUG_SYNC = 'now SIGNAL done';
+# Connecting to slave...
SET DEBUG_SYNC = 'now WAIT_FOR done';
SHOW DATABASES;
Database
@@ -399,7 +421,7 @@ mysql
rpl_backup
test
SET DEBUG_SYNC = 'reset';
-Try to start the slave after restore is done -- should succeed.
+# Try to start the slave after restore is done -- should succeed.
SLAVE START;
SHOW SLAVE STATUS;
Slave_IO_State #
@@ -442,11 +464,67 @@ Last_SQL_Errno 0
Last_SQL_Error
Replicate_Ignore_Server_Ids
Master_Server_Id 1
-Now stop the slave.
+# Now stop the slave.
SLAVE STOP;
+# Connecting to master...
+# First, reset replication.
+RESET MASTER;
+# Connecting to slave...
+RESET SLAVE;
+SET DEBUG_SYNC = 'reset';
+# Connecting to slave...
+START SLAVE;
+# Connecting to master...
+# Create a new database on the master.
+CREATE DATABASE not_replicated;
+CREATE TABLE not_replicated.t1 (a int);
+INSERT INTO not_replicated.t1 VALUES (200), (300), (400);
+SHOW DATABASES;
+Database
+information_schema
+mtr
+mysql
+not_replicated
+rpl_backup
+test
+# Connecting to slave...
+# Now let's see if it is replicated on the slave (shouldn't be).
+SHOW DATABASES;
+Database
+information_schema
+mtr
+mysql
+not_replicated
+rpl_backup
+test
+# Connecting to master...
+# Now back to the master to make a backup of the new database.
+# Backup_id = 505.
+BACKUP DATABASE not_replicated TO 'rpl_bup_m4.bak';
+backup_id
+505
+# Now let's run the restore and see if the slave stops.
+# Backup_id = 506.
+RESTORE FROM 'rpl_bup_m4.bak' OVERWRITE SKIP_GAP_EVENT;
+backup_id
+506
+# Let's ensure replication is still running.
+INSERT INTO rpl_backup.t1 VALUES (901), (902), (903);
+# Connecting to slave...
+SELECT * FROM rpl_backup.t1 WHERE a > 900;
+a
+901
+902
+903
+# Now stop the slave.
+SLAVE STOP;
+# Connecting to master...
FLUSH BACKUP LOGS;
PURGE BACKUP LOGS;
DROP DATABASE rpl_backup;
+DROP DATABASE not_replicated;
+# Connecting to slave...
FLUSH BACKUP LOGS;
PURGE BACKUP LOGS;
DROP DATABASE rpl_backup;
+DROP DATABASE not_replicated;
=== modified file 'mysql-test/suite/rpl/t/rpl_backup.test'
--- a/mysql-test/suite/rpl/t/rpl_backup.test 2009-01-29 21:17:59 +0000
+++ b/mysql-test/suite/rpl/t/rpl_backup.test 2009-02-09 22:23:14 +0000
@@ -4,12 +4,12 @@
--source include/master-slave.inc
--source include/not_embedded.inc
---source include/have_debug_sync.inc
--source include/have_debug.inc
+--echo # Connecting to master...
connection master;
---echo Create some data...
+--echo # Create some data...
CREATE DATABASE rpl_backup;
CREATE TABLE rpl_backup.t1 (a int);
INSERT INTO rpl_backup.t1 VALUES (1), (2), (3), (4), (5);
@@ -20,30 +20,32 @@ INSERT INTO rpl_backup.t1 VALUES (1), (2
# the backup event nor shall the master replicate any data produced
# (logged) by the backup.
---echo Remove all entries in the backup logs.
+--echo # Remove all entries in the backup logs.
FLUSH BACKUP LOGS;
PURGE BACKUP LOGS;
+--echo # Connecting to slave...
sync_slave_with_master;
connection slave;
---echo Get slave's datadir.
+--echo # Get slave's datadir.
let $MYSQLD_S_DATADIR= `select @@datadir`;
---echo Remove all entries in the backup logs.
+--echo # Remove all entries in the backup logs.
FLUSH BACKUP LOGS;
PURGE BACKUP LOGS;
---echo Get master's binlog position from the slave before backup.
+--echo # Get master's binlog position from the slave before backup.
let $slave_before_pos =
query_get_value("SHOW SLAVE STATUS", Read_Master_Log_Pos, 1);
+--echo # Connecting to master...
connection master;
---echo Get master's datadir.
+--echo # Get master's datadir.
let $MYSQLD_M_DATADIR= `select @@datadir`;
---echo Get master's binlog position before backup.
+--echo # Get master's binlog position before backup.
let $master_before_pos = query_get_value("SHOW MASTER STATUS", Position, 1);
#
@@ -55,25 +57,38 @@ SET SESSION debug="+d,set_backup_id";
replace_regex /(location ').*'/location '$MYSQLD_M_DATADIR\/master_data\/not\/there\/either\/rpl_backup_m1.bak'/ ;
# We are using debug insertion to set the first backup_id to
# 500 so we can expect the output of this operation to be 500.
---echo Backup_id = 500.
+#
+# NOTICE TO TEST DEVELOPERS:
+#
+# The use of the set_backup_id sets the first backup_id used to 500
+# for a master (or standalone) and 600 for a slave.
+#
+# The backup_id will be incremented by one after that (501, 502, ...)
+# If you change this test by inserting new test cases in the middle
+# of the test, you should also change the echo'ed comments to reflect
+# the renumbered steps.
+#
+--echo # Backup_id = 500.
BACKUP DATABASE rpl_backup TO 'rpl_bup_m1.bak';
+--remove_file $MYSQLD_M_DATADIR/rpl_bup_m1.bak
+
SET SESSION debug="-d";
---echo Show any events issued as a result of backup.
---echo Note: There should be none!
+--echo # Show any events issued as a result of backup.
+--echo # Note: There should be none!
--disable_query_log
eval SHOW BINLOG EVENTS FROM $master_before_pos;
--enable_query_log
---echo Verify backup run on master does not advance binlog pos.
---echo Get master's binlog position after backup.
+--echo # Verify backup run on master does not advance binlog pos.
+--echo # Get master's binlog position after backup.
let $master_after_pos = query_get_value("SHOW MASTER STATUS", Position, 1);
--disable_query_log
---echo Compare the before position of the master's binlog to
---echo the after position of the master's binlog. The result
---echo should be 0.
+--echo # Compare the before position of the master's binlog to
+--echo # the after position of the master's binlog. The result
+--echo # should be 0.
eval SELECT $master_after_pos - $master_before_pos AS Delta;
--enable_query_log
@@ -82,6 +97,7 @@ eval SELECT $master_after_pos - $master_
# Check slave's master position.
# Ensure replication is still working.
#
+--echo # Connecting to slave...
sync_slave_with_master;
connection slave;
@@ -89,18 +105,18 @@ connection slave;
# This tests is added to ensure none of the entries in the master's
# backup logs are replicated to the slave.
#
---echo Should have count(*) = 0.
+--echo # Should have count(*) = 0.
SELECT count(*) FROM mysql.backup_history;
---echo Verify backup run on master does not advance binlog pos.
---echo Get master's binlog position on the slave after backup.
+--echo # Verify backup run on master does not advance binlog pos.
+--echo # Get master's binlog position on the slave after backup.
let $slave_after_pos =
query_get_value("SHOW SLAVE STATUS", Read_Master_Log_Pos, 1);
--disable_query_log
---echo Compare the before position of the master's binlog to
---echo the after position of the slave's binlog as shown on
---echo on the slave. The result should be 0.
+--echo # Compare the before position of the master's binlog to
+--echo # the after position of the slave's binlog as shown on
+--echo # on the slave. The result should be 0.
eval SELECT $slave_after_pos - $slave_before_pos AS Delta;
--enable_query_log
@@ -108,10 +124,11 @@ eval SELECT $slave_after_pos - $slave_be
--replace_column 1 # 6 # 7 # 8 # 9 # 22 # 23 # 33 #
--query_vertical SHOW SLAVE STATUS
+--echo # Connecting to master...
connection master;
---echo Ensure replication is still working...
---echo Cleanup from last error on master and slave.
+--echo # Ensure replication is still working...
+--echo # Cleanup from last error on master and slave.
DELETE FROM rpl_backup.t1;
@@ -119,12 +136,13 @@ INSERT INTO rpl_backup.t1 VALUES (11), (
SELECT count(*) FROM rpl_backup.t1;
+--echo # Connecting to slave...
sync_slave_with_master;
connection slave;
SELECT count(*) FROM rpl_backup.t1;
---echo Cleanup backup logs.
+--echo # Cleanup backup logs.
FLUSH BACKUP LOGS;
PURGE BACKUP LOGS;
@@ -135,12 +153,14 @@ PURGE BACKUP LOGS;
# the progress log.
#
+--echo # Connecting to master...
connection master;
---echo First, get master's binlog position and filename.
+--echo # First, get master's binlog position and filename.
let $master_pos = query_get_value("SHOW MASTER STATUS", Position, 1);
let $master_file = query_get_value("SHOW MASTER STATUS", File, 1);
+--echo # Connecting to slave...
connection slave;
#
@@ -153,7 +173,7 @@ SET SESSION debug="+d,set_backup_id";
replace_regex /(location ').*'/location '$MYSQLD_S_DATADIR\/master_data\/not\/there\/either\/rpl_backup_s1.bak'/ ;
# We are using debug insertion to set the first backup_id to
# 600 so we can expect the output of this operation to be 600.
---echo Backup_id = 600.
+--echo # Backup_id = 600.
BACKUP DATABASE rpl_backup TO 'rpl_bup_s1.bak';
SET SESSION debug="-d";
@@ -169,17 +189,18 @@ let $preamble = 'Recording master binlog
let $middle = ''', position = ';
let $end = '.';
---echo Check saving of master's binlog information.
---echo Should have count(*) = 1.
+--echo # Check saving of master's binlog information.
+--echo # Should have count(*) = 1.
--disable_query_log
eval SELECT count(*) FROM mysql.backup_progress
WHERE Backup_id = 600 AND
notes = concat($preamble, "$master_file", $middle, $master_pos, $end);
--enable_query_log
---echo Should have count(*) = 1.
+--echo # Should have count(*) = 1.
SELECT count(*) FROM mysql.backup_history;
+--echo # Connecting to master...
connection master;
#
@@ -188,30 +209,34 @@ connection master;
INSERT INTO rpl_backup.t1 VALUES (10), (20), (30);
---echo Backup_id = 501.
+--echo # Backup_id = 501.
# Must mask command because dir in evaluation of $MYSQL... is not deterministic
---echo BACKUP DATABASE rpl_backup TO 'rpl_bup_m2.bak';
+--echo # BACKUP DATABASE rpl_backup TO 'rpl_bup_m2.bak';
--disable_query_log
eval BACKUP DATABASE rpl_backup TO '$MYSQLTEST_VARDIR/rpl_bup_m2.bak';
--enable_query_log
SELECT count(*) FROM rpl_backup.t1;
+--echo # Connecting to slave...
sync_slave_with_master;
connection slave;
SELECT count(*) FROM rpl_backup.t1;
---echo Make a backup for later use.
+--echo # Make a backup for later use.
# Must mask command because dir in evaluation of $MYSQL... is not deterministic
replace_regex /(location ').*'/location '$MYSQLD_S_DATADIR\/master_data\/not\/there\/either\/rpl_backup_s2.bak'/ ;
---echo Backup_id = 601.
+--echo # Backup_id = 601.
BACKUP DATABASE rpl_backup TO 'rpl_bup_s2.bak';
+--remove_file $MYSQLD_S_DATADIR/rpl_bup_s2.bak
+
#
# Use Case 2 - Restore performed on a master.
#
+--echo # Connecting to master...
connection master;
#
@@ -221,24 +246,24 @@ connection master;
CREATE TABLE rpl_backup.t2 (b int);
INSERT INTO rpl_backup.t2 VALUES (888), (999);
---echo Get master's binlog position before restore.
+--echo # Get master's binlog position before restore.
let $master_before_pos = query_get_value("SHOW MASTER STATUS", Position, 1);
# Must mask command because dir in evaluation of $MYSQL... is not deterministic
replace_regex /(location ').*'/location '$MYSQLTEST_VARDIR\/master_data\/not\/there\/either\/rpl_backup_m2.bak'/ ;
---echo Backup_id = 502.
---echo RESTORE FROM 'rpl_bup_m2.bak';
+--echo # Backup_id = 502.
+--echo # RESTORE FROM 'rpl_bup_m2.bak';
--disable_query_log
eval RESTORE FROM '$MYSQLTEST_VARDIR/rpl_bup_m2.bak' OVERWRITE;
--enable_query_log
---echo Show the incident event issued as a result of restore.
+--echo # Show the incident event issued as a result of restore.
--replace_column 2 # 5 #
--disable_query_log
eval SHOW BINLOG EVENTS FROM $master_before_pos;
--enable_query_log
---echo Showing tables on master.
+--echo # Showing tables on master.
SHOW FULL TABLES FROM rpl_backup;
SELECT count(*) FROM rpl_backup.t1;
@@ -246,19 +271,20 @@ SELECT count(*) FROM rpl_backup.t1;
#
# Wait for slave to stop as result of incident event.
#
+--echo # Connecting to slave...
connection slave;
source include/wait_for_slave_sql_to_stop.inc;
---echo Check slave got everything up to incident event.
---echo Should be two rows: 888, 999.
+--echo # Check slave got everything up to incident event.
+--echo # Should be two rows: 888, 999.
SELECT * FROM rpl_backup.t2 WHERE b > 800;
--replace_result $MASTER_MYPORT MASTER_PORT
--replace_column 1 # 6 # 7 # 8 # 9 # 22 # 23 # 33 #
--query_vertical SHOW SLAVE STATUS
---echo Show the slave stopped with an error.
+--echo # Show the slave stopped with an error.
LET $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
disable_query_log;
eval SELECT "$last_error" AS Last_SQL_Error;
@@ -275,7 +301,7 @@ START SLAVE;
# Sync with master to ensure nothing is replicated after incident event.
sync_with_master;
---echo Showing tables on slave.
+--echo # Showing tables on slave.
SHOW FULL TABLES FROM rpl_backup;
#
@@ -288,13 +314,15 @@ STOP SLAVE;
# Must mask command because dir in evaluation of $MYSQL... is not deterministic
replace_regex /(location ').*'/location '$MYSQLTEST_VARDIR\/master_data\/not\/there\/either\/rpl_backup_m2.bak'/ ;
---echo Backup_id = 602.
---echo RESTORE_FROM 'rpl_bup_m2.bak';
+--echo # Backup_id = 602.
+--echo # RESTORE_FROM 'rpl_bup_m2.bak';
--disable_query_log
eval RESTORE FROM '$MYSQLTEST_VARDIR/rpl_bup_m2.bak' OVERWRITE;
--enable_query_log
---echo Showing databases on slave.
+--remove_file $MYSQLTEST_VARDIR/rpl_bup_m2.bak
+
+--echo # Showing databases on slave.
SHOW DATABASES LIKE 'rpl_backup%';
SELECT count(*) FROM rpl_backup.t1;
@@ -302,22 +330,25 @@ SELECT count(*) FROM rpl_backup.t1;
START SLAVE;
--source include/wait_for_slave_to_start.inc
---echo Make a backup for later use.
---echo Backup_id = 603.
+--echo # Make a backup for later use.
+--echo # Backup_id = 603.
BACKUP DATABASE rpl_backup TO 'rpl_bup_s3.bak';
#
# Use Case 4 - Restore performed on a slave.
#
+--echo # Connecting to slave...
connection slave;
---echo Test restore on slave while replication turned on.
+--echo # Test restore on slave while replication turned on.
--error ER_RESTORE_ON_SLAVE
RESTORE FROM 'rpl_bup_s1.bak' OVERWRITE;
---echo Stop slave and restart after restore.
+--remove_file $MYSQLD_S_DATADIR/rpl_bup_s1.bak
+
+--echo # Stop slave and restart after restore.
STOP SLAVE;
--replace_column 1 #
@@ -326,12 +357,14 @@ RESTORE FROM 'rpl_bup_s3.bak' OVERWRITE;
START SLAVE;
--source include/wait_for_slave_to_start.inc
+--echo # Connecting to master...
connection master;
---echo Checking affect on replication.
+--echo # Checking affect on replication.
INSERT INTO rpl_backup.t1 VALUES (44), (55), (66);
SELECT * FROM rpl_backup.t1 ORDER BY a;
+--echo # Connecting to slave...
sync_slave_with_master;
connection slave;
SELECT * FROM rpl_backup.t1 ORDER BY a;
@@ -349,24 +382,26 @@ SELECT * FROM rpl_backup.t1 ORDER BY a;
# we have explicitly turned off binary logging.
#
---echo Stop replication and turn off binary log.
+--echo # Connecting to slave...
+--echo # Stop replication and turn off binary log.
connection slave;
STOP SLAVE;
--source include/wait_for_slave_to_stop.inc
+--echo # Connecting to master...
connection master;
SET @orig_sql_log_bin= @@sql_log_bin;
---echo Turn off binlog.
+--echo # Turn off binlog.
SET @@sql_log_bin= 0;
SHOW VARIABLES LIKE '%log_bin';
---echo Backup_id = 503.
+--echo # Backup_id = 503.
BACKUP DATABASE rpl_backup TO 'rpl_bup_m3.bak';
---echo Turn on binlog;
+--echo # Turn on binlog;
SET @@sql_log_bin= @orig_sql_log_bin;
SHOW VARIABLES LIKE '%log_bin';
@@ -376,27 +411,29 @@ SHOW VARIABLES LIKE '%log_bin';
RESET MASTER;
---echo Get master's binlog position before restore.
+--echo # Get master's binlog position before restore.
let $master_before_pos = query_get_value("SHOW MASTER STATUS", Position, 1);
---echo Backup_id = 504.
+--echo # Backup_id = 504.
RESTORE FROM 'rpl_bup_m3.bak' OVERWRITE;
---echo Get master's binlog position after restore.
+--remove_file $MYSQLD_M_DATADIR/rpl_bup_m3.bak
+
+--echo # Get master's binlog position after restore.
let $master_after_pos = query_get_value("SHOW MASTER STATUS", Position, 1);
---echo Show the incident event issued as a result of restore.
+--echo # Show the incident event issued as a result of restore.
--replace_column 2 # 5 #
--disable_query_log
eval SHOW BINLOG EVENTS FROM $master_before_pos;
--enable_query_log
---echo Compute the difference of the binlog positions.
---echo Result should be 0.
+--echo # Compute the difference of the binlog positions.
+--echo # Result should be 0.
--disable_query_log
---echo Compare the before position of the master's binlog to
---echo the after position of the master's binlog. The result
---echo should be 0.
+--echo # Compare the before position of the master's binlog to
+--echo # the after position of the master's binlog. The result
+--echo # should be 0.
eval SELECT $master_after_pos - $master_before_pos AS Delta;
--enable_query_log
@@ -406,22 +443,25 @@ eval SELECT $master_after_pos - $master_
RESET MASTER;
+--echo # Connecting to slave...
connection slave;
RESET SLAVE;
SET DEBUG_SYNC = 'reset';
+--echo # Connecting to slave...
connection slave1;
SET DEBUG_SYNC = 'before_restore_done SIGNAL restore_running WAIT_FOR proceed';
SEND RESTORE FROM 'rpl_bup_s3.bak' OVERWRITE;
+--echo # Connecting to slave...
connection slave;
SET DEBUG_SYNC = 'now WAIT_FOR restore_running';
---echo Try to start the slave while restore is running -- gets error.
+--echo # Try to start the slave while restore is running -- gets error.
--error ER_RESTORE_CANNOT_START_SLAVE
SLAVE START;
@@ -431,12 +471,16 @@ SET DEBUG_SYNC = 'now SIGNAL proceed';
--replace_column 1 # 6 # 7 # 8 # 9 # 22 # 23 # 33 #
--query_vertical SHOW SLAVE STATUS
+--echo # Connecting to slave...
connection slave1;
---echo Restore is now complete.
+--echo # Restore is now complete.
--replace_column 1 #
reap;
SET DEBUG_SYNC = 'now SIGNAL done';
+--remove_file $MYSQLD_S_DATADIR/rpl_bup_s3.bak
+
+--echo # Connecting to slave...
connection slave;
SET DEBUG_SYNC = 'now WAIT_FOR done';
@@ -445,7 +489,7 @@ SHOW DATABASES;
SET DEBUG_SYNC = 'reset';
---echo Try to start the slave after restore is done -- should succeed.
+--echo # Try to start the slave after restore is done -- should succeed.
SLAVE START;
--source include/wait_for_slave_to_start.inc
@@ -453,30 +497,97 @@ SLAVE START;
--replace_column 1 # 6 # 7 # 8 # 9 # 10 # 22 # 23 # 33 #
--query_vertical SHOW SLAVE STATUS
---echo Now stop the slave.
+--echo # Now stop the slave.
+SLAVE STOP;
+--source include/wait_for_slave_to_stop.inc
+
+#
+# Test case for BUG#39780 - Skip gap event on restore.
+#
+# The new SKIP_GAP_EVENT option for the RESTORE command
+# allows users to purposefully skip writing the gap event
+# when the restore is run on a master and the databases
+# being restored do not exist on the slave nor are they
+# intended to be on the slave.
+#
+
+--echo # Connecting to master...
+--echo # First, reset replication.
+connection master;
+RESET MASTER;
+
+--echo # Connecting to slave...
+connection slave;
+RESET SLAVE;
+SET DEBUG_SYNC = 'reset';
+
+--echo # Connecting to slave...
+connection slave;
+START SLAVE;
+--source include/wait_for_slave_to_start.inc
+
+--echo # Connecting to master...
+--echo # Create a new database on the master.
+connection master;
+
+CREATE DATABASE not_replicated;
+CREATE TABLE not_replicated.t1 (a int);
+INSERT INTO not_replicated.t1 VALUES (200), (300), (400);
+
+SHOW DATABASES;
+
+--echo # Connecting to slave...
+--echo # Now let's see if it is replicated on the slave (shouldn't be).
+sync_slave_with_master;
+connection slave;
+
+SHOW DATABASES;
+
+--echo # Connecting to master...
+--echo # Now back to the master to make a backup of the new database.
+connection master;
+
+--echo # Backup_id = 505.
+BACKUP DATABASE not_replicated TO 'rpl_bup_m4.bak';
+
+--echo # Now let's run the restore and see if the slave stops.
+--echo # Backup_id = 506.
+RESTORE FROM 'rpl_bup_m4.bak' OVERWRITE SKIP_GAP_EVENT;
+
+--remove_file $MYSQLD_M_DATADIR/rpl_bup_m4.bak
+
+--echo # Let's ensure replication is still running.
+INSERT INTO rpl_backup.t1 VALUES (901), (902), (903);
+
+--echo # Connecting to slave...
+sync_slave_with_master;
+connection slave;
+
+SELECT * FROM rpl_backup.t1 WHERE a > 900;
+
+--echo # Now stop the slave.
SLAVE STOP;
--source include/wait_for_slave_to_stop.inc
#
# Cleanup
#
+
+--echo # Connecting to master...
connection master;
FLUSH BACKUP LOGS;
PURGE BACKUP LOGS;
DROP DATABASE rpl_backup;
+DROP DATABASE not_replicated;
---remove_file $MYSQLD_M_DATADIR/rpl_bup_m1.bak
---remove_file $MYSQLTEST_VARDIR/rpl_bup_m2.bak
---remove_file $MYSQLD_M_DATADIR/rpl_bup_m3.bak
+--echo # Connecting to slave...
connection slave;
FLUSH BACKUP LOGS;
PURGE BACKUP LOGS;
DROP DATABASE rpl_backup;
+DROP DATABASE not_replicated;
---remove_file $MYSQLD_S_DATADIR/rpl_bup_s1.bak
---remove_file $MYSQLD_S_DATADIR/rpl_bup_s2.bak
---remove_file $MYSQLD_S_DATADIR/rpl_bup_s3.bak
=== modified file 'sql/backup/backup_kernel.h'
--- a/sql/backup/backup_kernel.h 2009-01-13 12:57:55 +0000
+++ b/sql/backup/backup_kernel.h 2009-02-09 22:23:14 +0000
@@ -30,7 +30,11 @@ void backup_shutdown();
Called from the big switch in mysql_execute_command() to execute
backup related statement
*/
-int execute_backup_command(THD*, LEX*, String*, bool);
+int execute_backup_command(THD *thd,
+ LEX *lex,
+ String *backupdir,
+ bool overwrite,
+ bool skip_gap_event);
// forward declarations
@@ -73,7 +77,7 @@ public:
const char*, bool);
Restore_info* prepare_for_restore(String *location,
LEX_STRING orig_loc,
- const char*);
+ const char*, bool);
int do_backup();
int do_restore(bool overwrite);
=== modified file 'sql/backup/kernel.cc'
--- a/sql/backup/kernel.cc 2009-02-09 18:17:55 +0000
+++ b/sql/backup/kernel.cc 2009-02-09 22:23:14 +0000
@@ -123,6 +123,9 @@ static int send_reply(Backup_restore_ctx
@param[in] backupdir value of the backupdir variable from server.
@param[in] overwrite whether or not restore should overwrite existing
DB with same name as in backup image
+ @param[in] skip_gap_event whether or not restore should skip writing
+ the gap event if run on a master in an active
+ replication scenario
@note This function sends response to the client (ok, result set or error).
@@ -134,7 +137,11 @@ static int send_reply(Backup_restore_ctx
*/
int
-execute_backup_command(THD *thd, LEX *lex, String *backupdir, bool overwrite)
+execute_backup_command(THD *thd,
+ LEX *lex,
+ String *backupdir,
+ bool overwrite,
+ bool skip_gap_event)
{
int res= 0;
@@ -209,7 +216,7 @@ execute_backup_command(THD *thd, LEX *le
{
Restore_info *info= context.prepare_for_restore(backupdir, lex->backup_dir,
- thd->query);
+ thd->query, skip_gap_event);
if (!info || !info->is_valid())
DBUG_RETURN(send_error(context, ER_BACKUP_RESTORE_PREPARE));
@@ -682,6 +689,7 @@ Backup_restore_ctx::prepare_for_backup(S
@param[in] backupdir path to the file where backup image is stored
@param[in] orig_loc path as specified on command line for backup image
@param[in] query RESTORE query starting the operation
+ @param[in] skip_gap_event TRUE means do not write gap event
@returns Pointer to a @c Restore_info instance containing catalogue of the
backup image (read from the image). NULL if errors were detected.
@@ -691,7 +699,8 @@ Backup_restore_ctx::prepare_for_backup(S
Restore_info*
Backup_restore_ctx::prepare_for_restore(String *backupdir,
LEX_STRING orig_loc,
- const char *query)
+ const char *query,
+ bool skip_gap_event)
{
using namespace backup;
@@ -834,7 +843,8 @@ Backup_restore_ctx::prepare_for_restore(
DEBUG_SYNC(m_thd, "after_disable_slave_connections");
- obs::write_incident_event(m_thd, obs::RESTORE_EVENT);
+ if (!skip_gap_event)
+ obs::write_incident_event(m_thd, obs::RESTORE_EVENT);
m_engage_binlog= TRUE;
obs::engage_binlog(FALSE);
}
=== modified file 'sql/lex.h'
--- a/sql/lex.h 2008-12-24 10:48:24 +0000
+++ b/sql/lex.h 2009-02-09 22:23:14 +0000
@@ -486,6 +486,7 @@ static SYMBOL symbols[] = {
{ "SHUTDOWN", SYM(SHUTDOWN)},
{ "SIGNED", SYM(SIGNED_SYM)},
{ "SIMPLE", SYM(SIMPLE_SYM)},
+ { "SKIP_GAP_EVENT", SYM(SKIP_GAP_EVENT_SYM)},
{ "SLAVE", SYM(SLAVE)},
{ "SNAPSHOT", SYM(SNAPSHOT_SYM)},
{ "SMALLINT", SYM(SMALLINT)},
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2009-02-04 10:49:16 +0000
+++ b/sql/sql_parse.cc 2009-02-09 22:23:14 +0000
@@ -45,7 +45,7 @@
@defgroup Runtime_Environment Runtime Environment
@{
*/
-int execute_backup_command(THD*, LEX*, String*, bool);
+int execute_backup_command(THD*, LEX*, String*, bool, bool);
/* Used in error handling only */
#define SP_TYPE_STRING(LP) \
@@ -2325,26 +2325,43 @@ mysql_execute_command(THD *thd)
/* Used to specify if RESTORE should overwrite existing db with same name */
bool overwrite_restore= false;
- Item *it= (Item *)lex->value_list.head();
+ /* Used to specify if RESTORE should skup writing the gap event. */
+ bool skip_gap_event= false;
+
+ List<Item> lit= lex->value_list;
+ Item *it= 0;
- // Item only set for RESTORE in sql_yacc.yy, no error checking of
- // item necessary
- if (it)
+ // value list only set for RESTORE in sql_yacc.yy, no error checking of
+ // item necessary for backup
+ while (lit.elements)
{
+ it= lit.pop();
/*
it is OK to only emulate fix_fields, because we need only
value of constant
*/
it->quick_fix_field();
-
- if ((int8)it->val_int() == 1)
- overwrite_restore= true;
+ int val= (int)it->val_int();
+ /*
+ Check options.
+ */
+ switch (val) {
+ /* OVERWRITE option */
+ case 1:
+ overwrite_restore= true;
+ break;
+ /* SKIP GAP EVENT option */
+ case 2:
+ skip_gap_event= true;
+ break;
+ }
}
/*
Note: execute_backup_command() sends a correct response to the client
(either ok, result set or error message).
*/
- if (execute_backup_command(thd, lex, &backupdir, overwrite_restore))
+ if (execute_backup_command(thd, lex, &backupdir, overwrite_restore,
+ skip_gap_event))
goto error;
break;
}
=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy 2009-01-29 21:17:59 +0000
+++ b/sql/sql_yacc.yy 2009-02-09 22:23:14 +0000
@@ -1075,6 +1075,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
%token SHUTDOWN
%token SIGNED_SYM
%token SIMPLE_SYM /* SQL-2003-N */
+%token SKIP_GAP_EVENT_SYM
%token SLAVE
%token SMALLINT /* SQL-2003-R */
%token SNAPSHOT_SYM
@@ -6461,7 +6462,7 @@ restore:
}
FROM
TEXT_STRING_sys
- opt_overwrite
+ opt_overwrite opt_skip_gap_event
{
Lex->backup_dir = $4;
}
@@ -6485,6 +6486,23 @@ opt_overwrite:
lex->value_list.push_front(it);
}
;
+
+opt_skip_gap_event:
+ /* empty */
+ {
+ LEX *lex= Lex;
+ Item *it= new Item_int((int8) 0);
+
+ lex->value_list.push_back(it);
+ }
+ | SKIP_GAP_EVENT_SYM
+ {
+ LEX *lex= Lex;
+ Item *it= new Item_int((int8) 2);
+
+ lex->value_list.push_back(it);
+ }
+ ;
backup:
BACKUP_SYM