mirror of
https://github.com/MariaDB/server.git
synced 2025-01-30 18:41:56 +01:00
a4c50983f4
This patch fixes three bugs as follows. First, aborting the server while purging binary logs might generate orphan files due to how the purge operation was implemented: (purge routine - sql/log.cc - MYSQL_BIN_LOG::purge_logs) 1 - register the files to be removed in a temporary buffer. 2 - update the log-bin.index. 3 - flush the log-bin.index. 4 - erase the files whose names where register in the temporary buffer in step 1. Thus a failure while executing step 4 would generate an orphan file. Second, a similar issue might happen while creating a new binary as follows: (create routine - sql/log.cc - MYSQL_BIN_LOG::open) 1 - open the new log-bin. 2 - update the log-bin.index. Thus a failure while executing step 1 would generate an orphan file. To fix these issues, we record the files to be purged or created before really removing or adding them. So if a failure happens such records can be used to automatically remove dangling files. The new steps might be outlined as follows: (purge routine - sql/log.cc - MYSQL_BIN_LOG::purge_logs) 1 - register the files to be removed in the log-bin.~rec~ placed in the data directory. 2 - update the log-bin.index. 3 - flush the log-bin.index. 4 - delete the log-bin.~rec~. (create routine - sql/log.cc - MYSQL_BIN_LOG::open) 1 - register the file to be created in the log-bin.~rec~ placed in the data directory. 2 - open the new log-bin. 3 - update the log-bin.index. 4 - delete the log-bin.~rec~. (recovery routine - sql/log.cc - MYSQL_BIN_LOG::open_index_file) 1 - open the log-bin.index. 2 - open the log-bin.~rec~. 3 - for each file in log-bin.~rec~. 3.1 Check if the file is in the log-bin.index and if so ignore it. 3.2 Otherwise, delete it. The third issue can be described as follows. The purge operation was allowing to remove a file in use thus leading to the loss of data and possible inconsistencies between the master and slave. Roughly, the routine was only taking into account the dump threads and so if a slave was not connect the file might be delete even though it was in use.
232 lines
6.5 KiB
Text
232 lines
6.5 KiB
Text
#
|
|
# testing of purging of binary log files bug#18199/Bug#18453
|
|
#
|
|
source include/have_log_bin.inc;
|
|
source include/not_embedded.inc;
|
|
call mtr.add_suppression('Attempting backtrace');
|
|
call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to process registered files that would be purged.');
|
|
call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file');
|
|
call mtr.add_suppression('Turning logging off for the whole duration of the MySQL server process.');
|
|
call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to clean registers before purging logs.');
|
|
let $old=`select @@debug`;
|
|
|
|
let $MYSQLD_DATADIR= `select @@datadir`;
|
|
let $INDEX=$MYSQLD_DATADIR/master-bin.index;
|
|
|
|
#
|
|
# testing purge binary logs TO
|
|
#
|
|
|
|
flush logs;
|
|
flush logs;
|
|
flush logs;
|
|
|
|
source include/show_binary_logs.inc;
|
|
remove_file $MYSQLD_DATADIR/master-bin.000001;
|
|
|
|
# there must be a warning with file names
|
|
replace_regex /\.[\\\/]master/master/;
|
|
purge binary logs TO 'master-bin.000004';
|
|
|
|
--echo *** must show a list starting from the 'TO' argument of PURGE ***
|
|
source include/show_binary_logs.inc;
|
|
|
|
#
|
|
# testing purge binary logs BEFORE
|
|
#
|
|
|
|
reset master;
|
|
|
|
flush logs;
|
|
flush logs;
|
|
flush logs;
|
|
remove_file $MYSQLD_DATADIR/master-bin.000001;
|
|
|
|
--echo *** must be a warning master-bin.000001 was not found ***
|
|
let $date=`select NOW() + INTERVAL 1 MINUTE`;
|
|
--disable_query_log
|
|
replace_regex /\.[\\\/]master/master/;
|
|
eval purge binary logs BEFORE '$date';
|
|
--enable_query_log
|
|
|
|
--echo *** must show one record, of the active binlog, left in the index file after PURGE ***
|
|
source include/show_binary_logs.inc;
|
|
|
|
#
|
|
# testing a fatal error
|
|
# Turning a binlog file into a directory must be a portable setup
|
|
#
|
|
|
|
reset master;
|
|
|
|
flush logs;
|
|
flush logs;
|
|
flush logs;
|
|
|
|
remove_file $MYSQLD_DATADIR/master-bin.000001;
|
|
mkdir $MYSQLD_DATADIR/master-bin.000001;
|
|
|
|
--error ER_BINLOG_PURGE_FATAL_ERR
|
|
purge binary logs TO 'master-bin.000002';
|
|
replace_regex /\.[\\\/]master/master/;
|
|
show warnings;
|
|
rmdir $MYSQLD_DATADIR/master-bin.000001;
|
|
--disable_warnings
|
|
reset master;
|
|
--enable_warnings
|
|
|
|
--echo # crash_purge_before_update_index
|
|
flush logs;
|
|
|
|
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
|
SET SESSION debug="+d,crash_purge_before_update_index";
|
|
--error 2013
|
|
purge binary logs TO 'master-bin.000002';
|
|
|
|
--enable_reconnect
|
|
--source include/wait_until_connected_again.inc
|
|
|
|
file_exists $MYSQLD_DATADIR/master-bin.000001;
|
|
file_exists $MYSQLD_DATADIR/master-bin.000002;
|
|
file_exists $MYSQLD_DATADIR/master-bin.000003;
|
|
--chmod 0644 $INDEX
|
|
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
|
-- eval SET @index=LOAD_FILE('$index')
|
|
-- replace_regex /\.[\\\/]master/master/
|
|
SELECT @index;
|
|
|
|
--echo # crash_purge_non_critical_after_update_index
|
|
flush logs;
|
|
|
|
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
|
SET SESSION debug="+d,crash_purge_non_critical_after_update_index";
|
|
--error 2013
|
|
purge binary logs TO 'master-bin.000004';
|
|
|
|
--enable_reconnect
|
|
--source include/wait_until_connected_again.inc
|
|
|
|
--error 1
|
|
file_exists $MYSQLD_DATADIR/master-bin.000001;
|
|
--error 1
|
|
file_exists $MYSQLD_DATADIR/master-bin.000002;
|
|
--error 1
|
|
file_exists $MYSQLD_DATADIR/master-bin.000003;
|
|
--chmod 0644 $INDEX
|
|
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
|
-- eval SET @index=LOAD_FILE('$index')
|
|
-- replace_regex /\.[\\\/]master/master/
|
|
SELECT @index;
|
|
|
|
--echo # crash_purge_critical_after_update_index
|
|
flush logs;
|
|
|
|
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
|
SET SESSION debug="+d,crash_purge_critical_after_update_index";
|
|
--error 2013
|
|
purge binary logs TO 'master-bin.000006';
|
|
|
|
--enable_reconnect
|
|
--source include/wait_until_connected_again.inc
|
|
|
|
--error 1
|
|
file_exists $MYSQLD_DATADIR/master-bin.000004;
|
|
--error 1
|
|
file_exists $MYSQLD_DATADIR/master-bin.000005;
|
|
file_exists $MYSQLD_DATADIR/master-bin.000006;
|
|
file_exists $MYSQLD_DATADIR/master-bin.000007;
|
|
--error 1
|
|
file_exists $MYSQLD_DATADIR/master-bin.000008;
|
|
--chmod 0644 $INDEX
|
|
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
|
-- eval SET @index=LOAD_FILE('$index')
|
|
-- replace_regex /\.[\\\/]master/master/
|
|
SELECT @index;
|
|
|
|
--echo # crash_create_non_critical_before_update_index
|
|
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
|
SET SESSION debug="+d,crash_create_non_critical_before_update_index";
|
|
--error 2013
|
|
flush logs;
|
|
|
|
--enable_reconnect
|
|
--source include/wait_until_connected_again.inc
|
|
|
|
file_exists $MYSQLD_DATADIR/master-bin.000008;
|
|
--error 1
|
|
file_exists $MYSQLD_DATADIR/master-bin.000009;
|
|
--chmod 0644 $INDEX
|
|
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
|
-- eval SET @index=LOAD_FILE('$index')
|
|
-- replace_regex /\.[\\\/]master/master/
|
|
SELECT @index;
|
|
|
|
--echo # crash_create_critical_before_update_index
|
|
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
|
SET SESSION debug="+d,crash_create_critical_before_update_index";
|
|
--error 2013
|
|
flush logs;
|
|
|
|
--enable_reconnect
|
|
--source include/wait_until_connected_again.inc
|
|
|
|
file_exists $MYSQLD_DATADIR/master-bin.000009;
|
|
--error 1
|
|
file_exists $MYSQLD_DATADIR/master-bin.000010;
|
|
--error 1
|
|
file_exists $MYSQLD_DATADIR/master-bin.000011;
|
|
--chmod 0644 $INDEX
|
|
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
|
-- eval SET @index=LOAD_FILE('$index')
|
|
-- replace_regex /\.[\\\/]master/master/
|
|
SELECT @index;
|
|
|
|
--echo # crash_create_after_update_index
|
|
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
|
SET SESSION debug="+d,crash_create_after_update_index";
|
|
--error 2013
|
|
flush logs;
|
|
|
|
--enable_reconnect
|
|
--source include/wait_until_connected_again.inc
|
|
|
|
file_exists $MYSQLD_DATADIR/master-bin.000010;
|
|
file_exists $MYSQLD_DATADIR/master-bin.000011;
|
|
--chmod 0644 $INDEX
|
|
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
|
-- eval SET @index=LOAD_FILE('$index')
|
|
-- replace_regex /\.[\\\/]master/master/
|
|
SELECT @index;
|
|
|
|
--echo #
|
|
--echo # This should put the server in unsafe state and stop
|
|
--echo # accepting any command. If we inject a fault at this
|
|
--echo # point and continue the execution the server crashes.
|
|
--echo # Besides the flush command does not report an error.
|
|
--echo #
|
|
|
|
--echo # fault_injection_registering_index
|
|
SET SESSION debug="+d,fault_injection_registering_index";
|
|
flush logs;
|
|
--source include/restart_mysqld.inc
|
|
|
|
--chmod 0644 $INDEX
|
|
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
|
-- eval SET @index=LOAD_FILE('$index')
|
|
-- replace_regex /\.[\\\/]master/master/
|
|
SELECT @index;
|
|
|
|
--echo # fault_injection_updating_index
|
|
SET SESSION debug="+d,fault_injection_updating_index";
|
|
flush logs;
|
|
--source include/restart_mysqld.inc
|
|
|
|
--chmod 0644 $INDEX
|
|
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
|
-- eval SET @index=LOAD_FILE('$index')
|
|
-- replace_regex /\.[\\\/]master/master/
|
|
SELECT @index;
|
|
|
|
eval SET SESSION debug="$old";
|
|
|
|
--echo End of tests
|