1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
# === Purpose ===
#
# Verify that disk full/out of space errors generated during the flush
# stage of binlog commit are properly handled by the server.
#
# === Implementation ===
#
# Simulate tempoary file write failures in below scenarios and verify the
# failures can be handled correctly.
# - Simulate binlog cache write failure in an INSERT which write data more than
# cache size.
# - Simulate my_b_flush_io_cache failure in an ROLLBACK TO.
# - Simulate my_b_flush_io_cache failure when reseting binlog cache in a
# ROLLBACK.
# - Simulate my_b_flush_io_cache failure when reseting binlog cache in a
# COMMIT
# - Simulate write failure
# - Simulate my_b_flush_io_cache failure when reseting binlog cache in
# disconnect
# - Simulate a binlog cache write failure when reinitializing it for
# copying to binlog. It should cause server abort if binlog_error_action
# is ABORT_SERVER
#
# === References ===
#
# Bug #27399620 BINLOG AND ENGINE BECOME INCONSISTENT WHEN BINLOG CACHE FILE
# GETS OUT OF SPACE
--source include/have_binlog_format_row.inc
--source include/have_log_bin.inc
--source include/have_debug.inc
# Don't test this under valgrind, memory leaks will occur
--source include/not_valgrind.inc
# Avoid CrashReporter popup on Mac
--source include/not_crashrep.inc
call mtr.add_suppression("An error occurred during flush stage of the commit");
call mtr.add_suppression("Attempting backtrace. You can use the following information to find out*");
call mtr.add_suppression(".*Error writing file.*");
RESET MASTER;
CREATE TABLE t1(c1 varchar(8192));
CREATE TABLE t2(c1 varchar(8192));
CREATE TABLE t3(c1 varchar(8192));
SET GLOBAL binlog_cache_size = 4096;
connect(con1,localhost,root,,);
--echo
--echo # Case 1 Simulate my_b_flush_io_cache failure when truncating binlog
--echo # cache. ROLLBACK TO triggers binlog cache truncation process.
--source include/save_binlog_position.inc
BEGIN;
INSERT INTO t1 VALUES (repeat('a', 2048));
# Below statemens in sp1 should not be binlogged
SAVEPOINT sp1;
INSERT INTO t2 VALUES (repeat('a', 4096));
INSERT INTO t3 VALUES (repeat('b', 4096));
# ROLLBACK to savepoint should not call my_b_flush_io_cache which
# caused extra events were logged before the fix.
SET SESSION debug = "+d,simulate_error_during_flush_cache_to_file";
ROLLBACK TO sp1;
SET SESSION debug = "-d,simulate_error_during_flush_cache_to_file";
INSERT INTO t1 VALUES (repeat('c', 8192));
COMMIT;
# The transaction should be binlogged correctly
--let $binlog_start= $binlog_position
--source include/show_binlog_events.inc
--echo
--echo # Case 2 Simulate my_b_flush_io_cache failure when reseting binlog cache
--echo # in ROLLBACK statement
BEGIN;
INSERT INTO t1 VALUES (repeat('a', 8192));
# When reseting binlog cache, it should not call my_b_flush_io_cache to flush
# data in binlog cache to temporary file. It caused assertion failure:
# binlog_cache_data::reset(): Assertion `is_binlog_empty()' before the fix.
SET SESSION debug = "+d,simulate_error_during_flush_cache_to_file";
ROLLBACK;
SET SESSION debug = "-d,simulate_error_during_flush_cache_to_file";
--echo
--echo # Case 3 CLIENT DISCONNECT. it is same to ROLLBACK
BEGIN;
INSERT INTO t1 VALUES (repeat('a', 8192));
SET SESSION debug = "+d,simulate_error_during_flush_cache_to_file";
--disconnect con1
--echo
--echo # Case 4 Simulate write failure when reinitializing binlog cache for
--echo # copying to binlog. The error should be ignored and cache
--echo # is cleared correctly if binlog_error_action is IGNORE_ERROR
--echo #
--connect(con1,localhost,root,,)
TRUNCATE t1;
--source include/save_binlog_position.inc
SET GLOBAL binlog_error_action = IGNORE_ERROR;
BEGIN;
INSERT INTO t1 VALUES (repeat('a', 8192));
SET SESSION debug = "+d,fault_injection_reinit_io_cache_while_flushing_to_file";
--replace_regex /.*Error writing file.*/Error writing file <tmp_file_name> (Errcode: ##)/
COMMIT;
SET SESSION debug = "-d,fault_injection_reinit_io_cache_while_flushing_to_file";
# Check that transaction is committed
--let $assert_cond = COUNT(*) = 1 FROM t1;
--let $assert_text = Count of elements in t1 should be 1.
# Check that error is present in error log
--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err
--let $assert_count = 1
--let $assert_select = An error occurred during flush stage of the commit. 'binlog_error_action' is set to 'IGNORE_ERROR'.
--let $assert_text = An error occurred during flush stage of the commit. 'binlog_error_action' is set to 'IGNORE_ERROR'.
--source include/assert_grep.inc
# Restart so that binary log is enabled again and we can do the below test
--disconnect con1
--connection default
--source include/restart_mysqld.inc
# Nothing should be logged
--let $binlog_start= $binlog_position
--source include/show_binlog_events.inc
--echo
--echo # Case 5 Simulate write failure when reinitializing binlog cache for
--echo # copying to binlog with ABORT_SERVER
--echo #
SET GLOBAL binlog_cache_size = 4096;
--connect(con1,localhost,root,,)
select @@global.binlog_cache_size;
TRUNCATE t2;
--source include/save_binlog_position.inc
SET GLOBAL binlog_error_action = ABORT_SERVER;
BEGIN;
INSERT INTO t2 VALUES (repeat('b', 8192));
--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
SET SESSION debug = "+d,fault_injection_reinit_io_cache_while_flushing_to_file";
--error ER_BINLOG_LOGGING_IMPOSSIBLE
COMMIT;
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
--enable_reconnect
--source include/wait_until_connected_again.inc
# Restart so that binary log is enabled again and we can do the below test
--source include/restart_mysqld.inc
select * from t2;
# Check that transaction is not committed
--let $assert_cond = COUNT(*) = 0 FROM t2;
--let $assert_text = Count of elements in t2 should be 0.
--source include/assert.inc
# Nothing should be logged
--let $binlog_start= $binlog_position
--source include/show_binlog_events.inc
# Cleanup
--disconnect con1
--connection default
--enable_reconnect
DROP TABLE t1, t2, t3;
RESET MASTER;
|