diff --git a/mysql-test/suite/rpl/include/rpl_bug72457.inc b/mysql-test/suite/rpl/include/rpl_bug72457.inc new file mode 100644 index 00000000000..a3d6da58540 --- /dev/null +++ b/mysql-test/suite/rpl/include/rpl_bug72457.inc @@ -0,0 +1,41 @@ +--source include/master-slave.inc + +call mtr.add_suppression("Slave SQL for channel '': The incident LOST_EVENTS occurred on the master\\. Message: The content of the statement cache is corrupted while writing a rollback record of the transaction to the binary log\\. Error_code:"); +call mtr.add_suppression("The content of the statement cache is corrupted while writing a rollback record of the transaction to the binary log\\. An incident event has been written to the binary log which will stop the slaves\\."); + +SET @saved_binlog_error_action = @@global.binlog_error_action; +SET GLOBAL binlog_error_action = IGNORE_ERROR; + +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; + +SET GLOBAL binlog_error_action = @saved_binlog_error_action; + +--let $rpl_only_running_threads = 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_bug72457_innodb.result b/mysql-test/suite/rpl/r/rpl_bug72457_innodb.result new file mode 100644 index 00000000000..55ce458b2b5 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_bug72457_innodb.result @@ -0,0 +1,49 @@ +# +# 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) +# +# Testing with --internal-tmp-disk-storage-engine=InnoDB and --default-tmp-storage-engine=InnoDB +# +include/assert.inc ['internal_tmp_disk_storage_engine' must be set to InnoDB] +include/assert.inc ['default_tmp_storage_engine' must be set to InnoDB] +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 for channel '': The incident LOST_EVENTS occurred on the master\\. Message: The content of the statement cache is corrupted while writing a rollback record of the transaction to the binary log\\. Error_code:"); +call mtr.add_suppression("The content of the statement cache is corrupted while writing a rollback record of the transaction to the binary log\\. An incident event has been written to the binary log which will stop the slaves\\."); +SET @saved_binlog_error_action = @@global.binlog_error_action; +SET GLOBAL binlog_error_action = IGNORE_ERROR; +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=13119] +Last_SQL_Error = 'The incident LOST_EVENTS occurred on the master. Message: The content of the statement cache is corrupted while writing a rollback record of the transaction to the binary log.' +include/stop_slave_io.inc +RESET SLAVE; +DROP TABLE t1; +[connection master] +DROP TABLE t1; +SET GLOBAL binlog_error_action = @saved_binlog_error_action; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_bug72457_myisam.result b/mysql-test/suite/rpl/r/rpl_bug72457_myisam.result new file mode 100644 index 00000000000..03f433ddb61 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_bug72457_myisam.result @@ -0,0 +1,49 @@ +# +# 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) +# +# Testing with --internal-tmp-disk-storage-engine=MyISAM and --default-tmp-storage-engine=MyISAM +# +include/assert.inc ['internal_tmp_disk_storage_engine' must be set to MyISAM] +include/assert.inc ['default_tmp_storage_engine' must be set to MyISAM] +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 for channel '': The incident LOST_EVENTS occurred on the master\\. Message: The content of the statement cache is corrupted while writing a rollback record of the transaction to the binary log\\. Error_code:"); +call mtr.add_suppression("The content of the statement cache is corrupted while writing a rollback record of the transaction to the binary log\\. An incident event has been written to the binary log which will stop the slaves\\."); +SET @saved_binlog_error_action = @@global.binlog_error_action; +SET GLOBAL binlog_error_action = IGNORE_ERROR; +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=13119] +Last_SQL_Error = 'The incident LOST_EVENTS occurred on the master. Message: The content of the statement cache is corrupted while writing a rollback record of the transaction to the binary log.' +include/stop_slave_io.inc +RESET SLAVE; +DROP TABLE t1; +[connection master] +DROP TABLE t1; +SET GLOBAL binlog_error_action = @saved_binlog_error_action; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_bug72457_innodb-master.opt b/mysql-test/suite/rpl/t/rpl_bug72457_innodb-master.opt new file mode 100644 index 00000000000..85156bd4346 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_bug72457_innodb-master.opt @@ -0,0 +1,2 @@ +--internal-tmp-disk-storage-engine=InnoDB +--default-tmp-storage-engine=InnoDB diff --git a/mysql-test/suite/rpl/t/rpl_bug72457_innodb.test b/mysql-test/suite/rpl/t/rpl_bug72457_innodb.test new file mode 100644 index 00000000000..2226924a3b0 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_bug72457_innodb.test @@ -0,0 +1,25 @@ +--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 # + +--echo # Testing with --internal-tmp-disk-storage-engine=InnoDB and --default-tmp-storage-engine=InnoDB +--echo # + +--let $assert_text = 'internal_tmp_disk_storage_engine' must be set to InnoDB +--let $assert_cond = @@internal_tmp_disk_storage_engine = "InnoDB" +--source include/assert.inc + +--let $assert_text = 'default_tmp_storage_engine' must be set to InnoDB +--let $assert_cond = @@default_tmp_storage_engine = "InnoDB" +--source include/assert.inc + +--source suite/rpl/include/rpl_bug72457.inc diff --git a/mysql-test/suite/rpl/t/rpl_bug72457_myisam-master.opt b/mysql-test/suite/rpl/t/rpl_bug72457_myisam-master.opt new file mode 100644 index 00000000000..cd07a061e7b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_bug72457_myisam-master.opt @@ -0,0 +1,2 @@ +--internal-tmp-disk-storage-engine=MyISAM +--default-tmp-storage-engine=MyISAM diff --git a/mysql-test/suite/rpl/t/rpl_bug72457_myisam.test b/mysql-test/suite/rpl/t/rpl_bug72457_myisam.test new file mode 100644 index 00000000000..75c8ac53c6a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_bug72457_myisam.test @@ -0,0 +1,26 @@ +--source include/have_debug.inc +--source include/have_binlog_format_row.inc +--source include/have_log_bin.inc +--source include/have_myisam.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 # + +--echo # Testing with --internal-tmp-disk-storage-engine=MyISAM and --default-tmp-storage-engine=MyISAM +--echo # + +--let $assert_text = 'internal_tmp_disk_storage_engine' must be set to MyISAM +--let $assert_cond = @@internal_tmp_disk_storage_engine = "MyISAM" +--source include/assert.inc + +--let $assert_text = 'default_tmp_storage_engine' must be set to MyISAM +--let $assert_cond = @@default_tmp_storage_engine = "MyISAM" +--source include/assert.inc + +--source suite/rpl/include/rpl_bug72457.inc diff --git a/sql/binlog.cc b/sql/binlog.cc index eca591911f0..67b8c9e1249 100644 --- a/sql/binlog.cc +++ b/sql/binlog.cc @@ -5140,20 +5140,27 @@ 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(false); - if (!thd->is_error()) DBUG_RETURN(checked); + bool checked = check_write_error_code(thd->get_stmt_da()->mysql_errno()); - switch (thd->get_stmt_da()->mysql_errno()) { - case ER_TRANS_CACHE_FULL: - case ER_STMT_CACHE_FULL: - case ER_ERROR_ON_WRITE: - case ER_BINLOG_LOGGING_IMPOSSIBLE: - checked = true; - break; + if (!checked) { + /* 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++) != nullptr && !checked) { + checked = check_write_error_code(err->mysql_errno()); + } } DBUG_PRINT("return", ("checked: %s", YESNO(checked))); DBUG_RETURN(checked); @@ -7181,11 +7188,10 @@ bool MYSQL_BIN_LOG::do_write_cache(IO_CACHE *cache, DBUG_EXECUTE_IF("simulate_tmpdir_partition_full", { DBUG_SET("+d,simulate_file_write_error"); }); - if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0)) { - DBUG_EXECUTE_IF("simulate_tmpdir_partition_full", - { DBUG_SET("-d,simulate_file_write_error"); }); - DBUG_RETURN(true); - } + int reinit_err = reinit_io_cache(cache, READ_CACHE, 0, 0, 0); + DBUG_EXECUTE_IF("simulate_tmpdir_partition_full", + { DBUG_SET("-d,simulate_file_write_error"); }); + if (reinit_err) DBUG_RETURN(true); uchar *buf = cache->read_pos; uint32 buf_len = my_b_bytes_in_cache(cache);