diff --git a/mysql-test/suite/rpl/r/rpl_bug72457.result b/mysql-test/suite/rpl/r/rpl_bug72457.result new file mode 100644 index 00000000000..f5e6729e245 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_bug72457.result @@ -0,0 +1,41 @@ +# +# Bug #72457 "Replication with no tmpdir space can break replication" +# (https://bugs.mysql.com/bug.php?id=72457) +# Bug #86991 "binlog corruption when tmpdir gets full" +# (https://bugs.mysql.com/bug.php?id=86991) +# Bug #88223 "Replication with no tmpdir space and InnoDB as tmp_storage_engine can break" +# (https://bugs.mysql.com/bug.php?id=88223) +# +include/master-slave.inc +Warnings: +Note #### Sending passwords in plain text without SSL/TLS is extremely insecure. +Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information. +[connection master] +call mtr.add_suppression("Slave SQL: The incident LOST_EVENTS occured on the master\\. Message: error writing to the binary log"); +CREATE TABLE t1(f1 TEXT) ENGINE=MyISAM; +INSERT INTO t1 VALUES(MD5(1)); +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +include/sync_slave_sql_with_master.inc +[connection master] +SET SESSION debug = "+d,simulate_tmpdir_partition_full"; +INSERT INTO t1 SELECT * FROM t1; +ERROR HY000: Error writing file (Errcode: ##) +SET SESSION debug = "-d,simulate_tmpdir_partition_full"; +[connection slave] +include/wait_for_slave_sql_error.inc [errno=1590] +Last_SQL_Error = 'The incident LOST_EVENTS occured on the master. Message: error writing to the binary log' +include/stop_slave_io.inc +RESET SLAVE; +DROP TABLE t1; +[connection master] +DROP TABLE t1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_bug72457.test b/mysql-test/suite/rpl/t/rpl_bug72457.test new file mode 100644 index 00000000000..b796b197ede --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_bug72457.test @@ -0,0 +1,48 @@ +--source include/have_debug.inc +--source include/have_binlog_format_row.inc +--source include/have_log_bin.inc + +--echo # +--echo # Bug #72457 "Replication with no tmpdir space can break replication" +--echo # (https://bugs.mysql.com/bug.php?id=72457) +--echo # Bug #86991 "binlog corruption when tmpdir gets full" +--echo # (https://bugs.mysql.com/bug.php?id=86991) +--echo # Bug #88223 "Replication with no tmpdir space and InnoDB as tmp_storage_engine can break" +--echo # (https://bugs.mysql.com/bug.php?id=88223) +--echo # + +--source include/master-slave.inc + +call mtr.add_suppression("Slave SQL: The incident LOST_EVENTS occured on the master\\. Message: error writing to the binary log"); + +CREATE TABLE t1(f1 TEXT) ENGINE=MyISAM; +INSERT INTO t1 VALUES(MD5(1)); + +--let $i = 10 +while($i) +{ + INSERT INTO t1 SELECT * FROM t1; + --dec $i +} +--source include/sync_slave_sql_with_master.inc + +--source include/rpl_connection_master.inc +SET SESSION debug = "+d,simulate_tmpdir_partition_full"; +--replace_regex /Error writing file .*/Error writing file (Errcode: ##)/ +--error 3 +INSERT INTO t1 SELECT * FROM t1; +SET SESSION debug = "-d,simulate_tmpdir_partition_full"; + +--source include/rpl_connection_slave.inc +--let $slave_sql_errno = convert_error(ER_SLAVE_INCIDENT) +--let $show_slave_sql_error = 1 +--source include/wait_for_slave_sql_error.inc +--source include/stop_slave_io.inc +RESET SLAVE; +DROP TABLE t1; + +--source include/rpl_connection_master.inc +DROP TABLE t1; + +--let $rpl_only_running_threads = 1 +--source include/rpl_end.inc diff --git a/sql/binlog.cc b/sql/binlog.cc index 68e0631547c..06a87a01517 100644 --- a/sql/binlog.cc +++ b/sql/binlog.cc @@ -3692,23 +3692,33 @@ int MYSQL_BIN_LOG::raw_get_current_log(LOG_INFO* linfo) return 0; } +static bool check_write_error_code(uint error_code) +{ + return error_code == ER_TRANS_CACHE_FULL || + error_code == ER_STMT_CACHE_FULL || + error_code == ER_ERROR_ON_WRITE || + error_code == ER_BINLOG_LOGGING_IMPOSSIBLE; +} + bool MYSQL_BIN_LOG::check_write_error(THD *thd) { DBUG_ENTER("MYSQL_BIN_LOG::check_write_error"); - bool checked= FALSE; - if (!thd->is_error()) - DBUG_RETURN(checked); + DBUG_RETURN(false); - switch (thd->get_stmt_da()->sql_errno()) + bool checked= check_write_error_code(thd->get_stmt_da()->sql_errno()); + + if (!checked) { - case ER_TRANS_CACHE_FULL: - case ER_STMT_CACHE_FULL: - case ER_ERROR_ON_WRITE: - case ER_BINLOG_LOGGING_IMPOSSIBLE: - checked= TRUE; - break; + /* Check all conditions for one that matches the expected error */ + const Sql_condition *err; + Diagnostics_area::Sql_condition_iterator it= + thd->get_stmt_da()->sql_conditions(); + while ((err= it++) != NULL && !checked) + { + checked= check_write_error_code(err->get_sql_errno()); + } } DBUG_PRINT("return", ("checked: %s", YESNO(checked))); DBUG_RETURN(checked);