#At file:///export/home/tmp/WL-4408n/mysql-6.0-backup/ based on revid:hema@stripped
2771 Hema Sridharan 2009-02-12
BUG#39056(backup_pipe.test) Test created for this defect which will help for regression. This patch will be now compatible with new mtr.
added:
mysql-test/suite/backup/r/backup_pipe.result
mysql-test/suite/backup/t/backup_pipe.test
modified:
sql/backup/kernel.cc
per-file messages:
mysql-test/suite/backup/r/backup_pipe.result
Result file for backup_pipe.test
mysql-test/suite/backup/t/backup_pipe.test
This test is created as part of bug#39056 for regression purpose.
sql/backup/kernel.cc
Debug syncronisation points added for testing backup / restore while another process is going on.
=== added file 'mysql-test/suite/backup/r/backup_pipe.result'
--- a/mysql-test/suite/backup/r/backup_pipe.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/r/backup_pipe.result 2009-02-12 20:09:30 +0000
@@ -0,0 +1,191 @@
+SET DEBUG_SYNC= 'reset';
+Verify that backup can be performed to pipe
+con1:
+Create database, tables and load data.
+CREATE DATABASE db1;
+CREATE DATABASE db2;
+CREATE TABLE db1.t1(id int);
+INSERT INTO db1.t1 VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9);
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+CREATE TABLE db2.t2(a char(5));
+INSERT INTO db2.t2 VALUES('a'),('b'),('c'),('d'),('e'),('f'),('g'),('h');
+INSERT INTO db2.t2 SELECT * FROM db2.t2;
+INSERT INTO db2.t2 SELECT * FROM db2.t2;
+INSERT INTO db2.t2 SELECT * FROM db2.t2;
+SELECT COUNT(*) FROM db1.t1;
+COUNT(*)
+144
+SELECT COUNT(*) FROM db2.t2;
+COUNT(*)
+64
+con2:
+Create pipe.
+con1:
+PURGE BACKUP LOGS;
+Start backup to pipe.
+BACKUP DATABASE db1 TO 'db1_pipe';
+con2:
+Cat the output to a file.
+con1:
+backup_id
+#
+verify backup history log:
+SELECT backup_state, command, operation, num_objects FROM mysql.backup_history;
+backup_state command operation num_objects
+complete BACKUP DATABASE db1 TO 'db1_pipe' backup 1
+Drop database and perform restore from a pipe.
+DROP DATABASE db1;
+PURGE BACKUP LOGS;
+Performing restore from pipe
+RESTORE FROM 'db1_pipe';
+con2:
+Cat the output to a pipe (for restore)
+con1:
+backup_id
+#
+SHOW TABLES FROM db1;
+Tables_in_db1
+t1
+SHOW TABLES FROM db2;
+Tables_in_db2
+t2
+SELECT COUNT(*) FROM db1.t1;
+COUNT(*)
+144
+SELECT COUNT(*) FROM db2.t2;
+COUNT(*)
+64
+SELECT backup_state, command, operation, num_objects FROM mysql.backup_history;
+backup_state command operation num_objects
+complete RESTORE FROM 'db1_pipe' restore 1
+DROP DATABASE db1;
+verify that restore can be performed from output file that reads from
+pipe
+PURGE BACKUP LOGS;
+RESTORE FROM 'db1_file';
+backup_id
+#
+verify data contents are intact
+SHOW TABLES FROM db1;
+Tables_in_db1
+t1
+SELECT COUNT(*) FROM db1.t1;
+COUNT(*)
+144
+SELECT backup_state, command, operation, num_objects FROM mysql.backup_history;
+backup_state command operation num_objects
+complete RESTORE FROM 'db1_file' restore 1
+con1:
+Start backup to pipe:
+SET DEBUG_SYNC= 'before_backup_open_stream SIGNAL running WAIT_FOR backup';
+BACKUP DATABASE db1 TO 'db1_pipe';
+con3:
+Attempt to run a backup while another is in progress.
+SET DEBUG_SYNC= 'now WAIT_FOR running';
+BACKUP DATABASE db2 TO 'db2.bak';
+ERROR HY000: Can't execute this command because another BACKUP/RESTORE operation is in progress
+Wait for first backup to complete
+SET DEBUG_SYNC= 'now SIGNAL backup';
+con2:
+Cat the output to a file.
+con1:
+backup_id
+#
+con3:
+Start another backup to the same pipe.
+BACKUP DATABASE db2 TO 'db1_pipe';
+con2:
+Cat the output to a file.
+con3:
+backup_id
+#
+DROP DATABASE db1;
+DROP DATABASE db2;
+# con1:
+# Perform concurrent restore operation and ensure that there is
+# no server crash
+Execute restore operation
+SET DEBUG_SYNC= 'before_restore_open_stream SIGNAL running WAIT_FOR restore';
+RESTORE FROM 'db1_pipe';
+con3:
+Attempt to run a restore while another is in progress.
+SET DEBUG_SYNC= 'now WAIT_FOR running';
+RESTORE FROM 'db1_pipe';
+ERROR HY000: Can't execute this command because another BACKUP/RESTORE operation is in progress
+Attempt to run a backup while restore is in progress.
+BACKUP DATABASE db2 TO 'db2.bak';
+ERROR HY000: Can't execute this command because another BACKUP/RESTORE operation is in progress
+Wait for first restore to complete
+SET DEBUG_SYNC= 'now SIGNAL restore';
+con2:
+Cat the output to pipe
+con1:
+backup_id
+#
+con3:
+Perform restore from same pipe
+RESTORE FROM 'db1_pipe';
+con2:
+Cat the output to pipe
+con3:
+backup_id
+#
+verify the tables and data in db1 & db2.
+SHOW TABLES FROM db1;
+Tables_in_db1
+t1
+SHOW TABLES FROM db2;
+Tables_in_db2
+t2
+SELECT COUNT(*) FROM db1.t1;
+COUNT(*)
+144
+SELECT COUNT(*) FROM db2.t2;
+COUNT(*)
+64
+DROP DATABASE db1;
+
+# Perform concurrent backup in one connection and restore in another
+Execute backup operation
+SET DEBUG_SYNC= 'before_backup_open_stream SIGNAL running WAIT_FOR backup';
+BACKUP DATABASE db2 TO 'db1_pipe';
+con3:
+Attempt to perform backup while restore is in progress.
+SET DEBUG_SYNC= 'now WAIT_FOR running';
+RESTORE FROM 'db1_pipe';
+ERROR HY000: Can't execute this command because another BACKUP/RESTORE operation is in progress
+Wait for first backup to complete
+SET DEBUG_SYNC= 'now SIGNAL backup';
+con2:
+Cat the output to pipe
+con1:
+backup_id
+#
+con3:
+Perform backup to same pipe
+RESTORE FROM 'db1_pipe';
+con2:
+Cat the output to file
+con3:
+backup_id
+#
+verify the tables and data in db1 & db2.
+SHOW TABLES FROM db1;
+Tables_in_db1
+t1
+SHOW TABLES FROM db2;
+Tables_in_db2
+t2
+SELECT COUNT(*) FROM db1.t1;
+COUNT(*)
+144
+SELECT COUNT(*) FROM db2.t2;
+COUNT(*)
+64
+SET DEBUG_SYNC= 'reset';
+Test cleanup
+DROP DATABASE db1;
+DROP DATABASE db2;
=== added file 'mysql-test/suite/backup/t/backup_pipe.test'
--- a/mysql-test/suite/backup/t/backup_pipe.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/t/backup_pipe.test 2009-02-12 20:09:30 +0000
@@ -0,0 +1,292 @@
+#
+# This test is for BUG#39056. (Mysql Server crash for concurrent backup
+# operations with one of them is backup to pipe)
+# Verify that,
+# a) Backup / Restore can be performed to / from pipe
+# b) Execute concurrent backup / restore operation when one of them is backup
+# to pipe.
+#
+# Note: At present backup to named pipes cannot be executed in standard windows
+# installs. Therefore, this test is not designed to run in windows.
+
+--source include/have_innodb.inc
+--source include/not_embedded.inc
+--source include/not_windows.inc
+--source include/have_debug_sync.inc
+
+# Suppress warning about expected backup/restore errors
+disable_query_log;
+call mtr.add_suppression("Backup:");
+call mtr.add_suppression("Restore:");
+enable_query_log;
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+--disable_warnings
+SET DEBUG_SYNC= 'reset';
+--enable_warnings
+
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+connect (con3,localhost,root,,);
+
+--echo Verify that backup can be performed to pipe
+--echo con1:
+connection con1;
+
+--echo Create database, tables and load data.
+CREATE DATABASE db1;
+CREATE DATABASE db2;
+CREATE TABLE db1.t1(id int);
+INSERT INTO db1.t1 VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9);
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+
+CREATE TABLE db2.t2(a char(5));
+INSERT INTO db2.t2 VALUES('a'),('b'),('c'),('d'),('e'),('f'),('g'),('h');
+INSERT INTO db2.t2 SELECT * FROM db2.t2;
+INSERT INTO db2.t2 SELECT * FROM db2.t2;
+INSERT INTO db2.t2 SELECT * FROM db2.t2;
+
+SELECT COUNT(*) FROM db1.t1;
+SELECT COUNT(*) FROM db2.t2;
+
+--echo con2:
+connection con2;
+
+--echo Create pipe.
+# mkfifo helps to create a pipe(something similar to file).
+# chmod helps for providing specific access mode to the file. chmod 666
+# provides read and write access to user.
+# "chmod 666 pipe_name" allows to read and write to the pipe.
+
+--exec mkfifo $MYSQLD_DATADIR/db1_pipe
+--exec chmod 666 $MYSQLD_DATADIR/db1_pipe
+
+--echo con1:
+connection con1;
+PURGE BACKUP LOGS;
+--echo Start backup to pipe.
+send BACKUP DATABASE db1 TO 'db1_pipe';
+
+--echo con2:
+connection con2;
+--echo Cat the output to a file.
+# cat helps in redirecting the output from pipe to another file.
+--exec cat $MYSQLD_DATADIR/db1_pipe > $MYSQLD_DATADIR/db1_file
+
+--echo con1:
+connection con1;
+--replace_column 1 #
+reap;
+
+--echo verify backup history log:
+SELECT backup_state, command, operation, num_objects FROM mysql.backup_history;
+--echo Drop database and perform restore from a pipe.
+DROP DATABASE db1;
+
+PURGE BACKUP LOGS;
+--echo Performing restore from pipe
+send RESTORE FROM 'db1_pipe';
+
+--echo con2:
+connection con2;
+--echo Cat the output to a pipe (for restore)
+--exec cat $MYSQLD_DATADIR/db1_file > $MYSQLD_DATADIR/db1_pipe
+
+--echo con1:
+connection con1;
+--replace_column 1 #
+reap;
+
+SHOW TABLES FROM db1;
+SHOW TABLES FROM db2;
+SELECT COUNT(*) FROM db1.t1;
+SELECT COUNT(*) FROM db2.t2;
+SELECT backup_state, command, operation, num_objects FROM mysql.backup_history;
+
+DROP DATABASE db1;
+
+--echo verify that restore can be performed from output file that reads from
+--echo pipe
+
+PURGE BACKUP LOGS;
+--replace_column 1 #
+RESTORE FROM 'db1_file';
+
+--echo verify data contents are intact
+
+SHOW TABLES FROM db1;
+SELECT COUNT(*) FROM db1.t1;
+SELECT backup_state, command, operation, num_objects FROM mysql.backup_history;
+--remove_file $MYSQLD_DATADIR/db1_file
+
+#
+# Test 2: Concurrent backup / restore operation(Test case for bug#39056)
+#
+
+--echo con1:
+--echo Start backup to pipe:
+SET DEBUG_SYNC= 'before_backup_open_stream SIGNAL running WAIT_FOR backup';
+send BACKUP DATABASE db1 TO 'db1_pipe';
+
+--echo con3:
+connection con3;
+--echo Attempt to run a backup while another is in progress.
+SET DEBUG_SYNC= 'now WAIT_FOR running';
+--error ER_BACKUP_RUNNING
+BACKUP DATABASE db2 TO 'db2.bak';
+
+--echo Wait for first backup to complete
+SET DEBUG_SYNC= 'now SIGNAL backup';
+
+--echo con2:
+connection con2;
+--echo Cat the output to a file.
+--exec cat $MYSQLD_DATADIR/db1_pipe > $MYSQLD_DATADIR/db1_file
+
+--echo con1:
+connection con1;
+--replace_column 1 #
+reap;
+
+--echo con3:
+connection con3;
+--echo Start another backup to the same pipe.
+send BACKUP DATABASE db2 TO 'db1_pipe';
+
+--echo con2:
+connection con2;
+
+--echo Cat the output to a file.
+--exec cat $MYSQLD_DATADIR/db1_pipe > $MYSQLD_DATADIR/db2_file
+
+--echo con3:
+connection con3;
+--replace_column 1 #
+reap;
+
+DROP DATABASE db1;
+DROP DATABASE db2;
+
+--echo # con1:
+--echo # Perform concurrent restore operation and ensure that there is
+--echo # no server crash
+connection con1;
+--echo Execute restore operation
+SET DEBUG_SYNC= 'before_restore_open_stream SIGNAL running WAIT_FOR restore';
+send RESTORE FROM 'db1_pipe';
+
+--echo con3:
+connection con3;
+--echo Attempt to run a restore while another is in progress.
+SET DEBUG_SYNC= 'now WAIT_FOR running';
+--error ER_BACKUP_RUNNING
+RESTORE FROM 'db1_pipe';
+
+--echo Attempt to run a backup while restore is in progress.
+--error ER_BACKUP_RUNNING
+BACKUP DATABASE db2 TO 'db2.bak';
+
+--echo Wait for first restore to complete
+SET DEBUG_SYNC= 'now SIGNAL restore';
+
+--echo con2:
+connection con2;
+--echo Cat the output to pipe
+--exec cat $MYSQLD_DATADIR/db1_file > $MYSQLD_DATADIR/db1_pipe
+
+--echo con1:
+connection con1;
+--replace_column 1 #
+reap;
+
+--echo con3:
+connection con3;
+--echo Perform restore from same pipe
+send RESTORE FROM 'db1_pipe';
+
+--echo con2:
+connection con2;
+--echo Cat the output to pipe
+--exec cat $MYSQLD_DATADIR/db2_file > $MYSQLD_DATADIR/db1_pipe
+
+--echo con3:
+connection con3;
+--replace_column 1 #
+reap;
+
+--echo verify the tables and data in db1 & db2.
+
+SHOW TABLES FROM db1;
+SHOW TABLES FROM db2;
+SELECT COUNT(*) FROM db1.t1;
+SELECT COUNT(*) FROM db2.t2;
+--remove_file $MYSQLD_DATADIR/db2_file
+
+DROP DATABASE db1;
+
+--echo
+--echo # Perform concurrent backup in one connection and restore in another
+connection con1;
+--echo Execute backup operation
+SET DEBUG_SYNC= 'before_backup_open_stream SIGNAL running WAIT_FOR backup';
+send BACKUP DATABASE db2 TO 'db1_pipe';
+
+--echo con3:
+connection con3;
+--echo Attempt to perform backup while restore is in progress.
+SET DEBUG_SYNC= 'now WAIT_FOR running';
+--error ER_BACKUP_RUNNING
+RESTORE FROM 'db1_pipe';
+
+--echo Wait for first backup to complete
+SET DEBUG_SYNC= 'now SIGNAL backup';
+
+--echo con2:
+connection con2;
+--echo Cat the output to pipe
+--exec cat $MYSQLD_DATADIR/db1_pipe > $MYSQLD_DATADIR/db2_file
+
+--echo con1:
+connection con1;
+--replace_column 1 #
+reap;
+
+--echo con3:
+connection con3;
+--echo Perform backup to same pipe
+send RESTORE FROM 'db1_pipe';
+
+--echo con2:
+connection con2;
+--echo Cat the output to file
+--exec cat $MYSQLD_DATADIR/db1_file > $MYSQLD_DATADIR/db1_pipe
+
+--echo con3:
+connection con3;
+--replace_column 1 #
+reap;
+
+--echo verify the tables and data in db1 & db2.
+
+SHOW TABLES FROM db1;
+SHOW TABLES FROM db2;
+SELECT COUNT(*) FROM db1.t1;
+SELECT COUNT(*) FROM db2.t2;
+
+--disable_warnings
+SET DEBUG_SYNC= 'reset';
+--enable_warnings
+
+--echo Test cleanup
+
+DROP DATABASE db1;
+DROP DATABASE db2;
+--remove_file $MYSQLD_DATADIR/db1_pipe
+--remove_file $MYSQLD_DATADIR/db1_file
+--remove_file $MYSQLD_DATADIR/db2_file
+
+
=== modified file 'sql/backup/kernel.cc'
--- a/sql/backup/kernel.cc 2009-02-11 16:22:12 +0000
+++ b/sql/backup/kernel.cc 2009-02-12 20:09:30 +0000
@@ -624,6 +624,7 @@ Backup_restore_ctx::prepare_for_backup(S
/*
Open output stream.
*/
+ DEBUG_SYNC(m_thd, "before_backup_open_stream");
Output_stream *s= new Output_stream(*this,
&m_path,
with_compression);
@@ -746,7 +747,7 @@ Backup_restore_ctx::prepare_for_restore(
/*
Open input stream.
*/
-
+ DEBUG_SYNC(m_thd, "before_restore_open_stream");
Input_stream *s= new Input_stream(*this, &m_path);
m_stream= s;