From db2d812d1b2b554e10cebf9809e26d1d1dc4bbc9 Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Tue, 16 Dec 2003 11:10:50 +0100 Subject: [PATCH] Fix for BUG#2083 "EE_ error codes (EE_DELETE, EE_WRITE) end up in the binlog, making slave stop". The problem was that during execution of the command on the master, an error can occur (for example, not space left on device, then mysqld waits and when there is space it completes successfully: so finally it worked but the error EE_WRITE remains in thd->net.last_errno and thd->net.last_error). To know if finally the command succeeded, we test the 'error' variable in every place, and if it shows no failure we reset thd->net.last_err* using the function THD::clear_error() which is backported from 4.1. A new test to see if now only real errors get to the binlog (note: the test uses "rm"). Also a bit of memory free/alloc saving in log_event.cc (do not free the whole mem_root after every query in the slave SQL thread: we can keep the initial block of it; which will be freed when the thread terminates). --- mysql-test/r/rpl_EE_error.result | 16 ++++++++++++++++ mysql-test/t/rpl_EE_error.test | 30 ++++++++++++++++++++++++++++++ sql/log_event.cc | 6 +++--- sql/sql_acl.cc | 1 + sql/sql_base.cc | 2 +- sql/sql_class.h | 9 +++++++++ sql/sql_db.cc | 2 ++ sql/sql_delete.cc | 5 +++++ sql/sql_insert.cc | 6 +++++- sql/sql_parse.cc | 2 ++ sql/sql_rename.cc | 1 + sql/sql_table.cc | 5 +++++ sql/sql_update.cc | 4 ++++ 13 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 mysql-test/r/rpl_EE_error.result create mode 100644 mysql-test/t/rpl_EE_error.test diff --git a/mysql-test/r/rpl_EE_error.result b/mysql-test/r/rpl_EE_error.result new file mode 100644 index 00000000000..a5043250df6 --- /dev/null +++ b/mysql-test/r/rpl_EE_error.result @@ -0,0 +1,16 @@ +slave stop; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +slave start; +create table t1 (a int) type=myisam; +flush tables; +drop table t1; +create table t1 (a int, unique(a)) type=myisam; +set sql_log_bin=0; +insert into t1 values(2); +set sql_log_bin=1; +insert into t1 values(1),(2); +Duplicate entry '2' for key 1 +drop table t1; diff --git a/mysql-test/t/rpl_EE_error.test b/mysql-test/t/rpl_EE_error.test new file mode 100644 index 00000000000..de69c4897c3 --- /dev/null +++ b/mysql-test/t/rpl_EE_error.test @@ -0,0 +1,30 @@ +# See if an EE_ error in one event of the master's binlog stops replication +# (it should not: in this configuration the EE_ error is probably not +# critical). Example: you do a DROP TABLE on a table which has no MYI file +# check if START SLAVE, RESET SLAVE, CHANGE MASTER reset Last_slave_error and +# Last_slave_errno in SHOW SLAVE STATUS (1st and 3rd commands did not: bug 986). + +source include/master-slave.inc; + +create table t1 (a int) type=myisam; +flush tables; +system rm ./var/master-data/test/t1.MYI ; +drop table t1; +save_master_pos; +connection slave; +sync_with_master; + +# Now a real error. + +connection master; +create table t1 (a int, unique(a)) type=myisam; +set sql_log_bin=0; +insert into t1 values(2); +set sql_log_bin=1; +save_master_pos; +--error 1062; +insert into t1 values(1),(2); +drop table t1; +save_master_pos; +connection slave; +wait_for_slave_to_stop; diff --git a/sql/log_event.cc b/sql/log_event.cc index 9779b7401dd..4413a77c364 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1922,7 +1922,7 @@ Default database: '%s'", // assume no convert for next query unless set explictly thd->variables.convert_set = 0; close_thread_tables(thd); - free_root(&thd->mem_root,0); + free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); return (thd->query_error ? thd->query_error : Log_event::exec_event(rli)); } @@ -2094,10 +2094,10 @@ Slave: load data infile on table '%s' at log position %s in log \ slave_print_error(rli,sql_errno,"\ Error '%s' running LOAD DATA INFILE on table '%s'. Default database: '%s'", err, (char*)table_name, print_slave_db_safe(db)); - free_root(&thd->mem_root,0); + free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); return 1; } - free_root(&thd->mem_root,0); + free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); if (thd->fatal_error) { diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 03a359d44e7..e8e2f808b7e 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1130,6 +1130,7 @@ bool change_password(THD *thd, const char *host, const char *user, acl_user->user ? acl_user->user : "", acl_user->host.hostname ? acl_user->host.hostname : "", new_password)); + thd->clear_error(); mysql_update_log.write(thd, buff, query_length); Query_log_event qinfo(thd, buff, query_length, 0); mysql_bin_log.write(&qinfo); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e4694adb9a2..cf42109fb9a 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -575,8 +575,8 @@ void close_temporary_tables(THD *thd) if (query && found_user_tables && mysql_bin_log.is_open()) { /* The -1 is to remove last ',' */ + thd->clear_error(); Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0); - qinfo.error_code=0; mysql_bin_log.write(&qinfo); } thd->temporary_tables=0; diff --git a/sql/sql_class.h b/sql/sql_class.h index 9287a0c8c79..2899c643536 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -590,6 +590,15 @@ public: void add_changed_table(TABLE *table); void add_changed_table(const char *key, long key_length); CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length); +#ifndef EMBEDDED_LIBRARY + inline void clear_error() + { + net.last_error[0]= 0; + net.last_errno= 0; + } +#else + void clear_error(); +#endif }; /* Flags for the THD::system_thread (bitmap) variable */ diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 6251b1ec624..6c11067ac8f 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -86,6 +86,7 @@ int mysql_create_db(THD *thd, char *db, uint create_options, bool silent) mysql_update_log.write(thd,thd->query, thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } @@ -176,6 +177,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 34a79ecd78d..ef90cd55730 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -175,6 +175,8 @@ cleanup: mysql_update_log.write(thd,thd->query, thd->query_length); if (mysql_bin_log.is_open()) { + if (error <= 0) + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, log_delayed); if (mysql_bin_log.write(&qinfo) && transactional_table) @@ -479,6 +481,8 @@ bool multi_delete::send_eof() mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { + if (error <= 0) + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, log_delayed); if (mysql_bin_log.write(&qinfo) && !normal_tables) @@ -591,6 +595,7 @@ end: mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, thd->tmp_table); mysql_bin_log.write(&qinfo); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 3414e76e092..00545f04c44 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -310,6 +310,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List &fields, mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { + if (error <= 0) + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, log_delayed); if (mysql_bin_log.write(&qinfo) && transactional_table) @@ -1196,7 +1198,7 @@ bool delayed_insert::handle_inserts(void) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); using_ignore=1; } - thd.net.last_errno = 0; // reset error for binlog + thd.clear_error(); // reset error for binlog if (write_record(table,&info)) { info.error_count++; // Ignore errors @@ -1391,6 +1393,8 @@ bool select_insert::send_eof() mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { + if (!error) + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, table->file->has_transactions()); mysql_bin_log.write(&qinfo); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c867112bb2a..9be861cf2c9 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2461,6 +2461,7 @@ mysql_execute_command(void) mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } @@ -2481,6 +2482,7 @@ mysql_execute_command(void) mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index d7e998264f3..05d31c173d3 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -82,6 +82,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list) mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 94ecf33b9c6..07fc6971502 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -237,6 +237,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, mysql_update_log.write(thd, thd->query,thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, tmp_table_deleted && !some_tables_deleted); mysql_bin_log.write(&qinfo); @@ -779,6 +780,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, mysql_update_log.write(thd,thd->query, thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, test(create_info->options & HA_LEX_CREATE_TMP_TABLE)); @@ -1561,6 +1563,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } @@ -1931,6 +1934,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, mysql_update_log.write(thd, thd->query,thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } @@ -2063,6 +2067,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, mysql_update_log.write(thd, thd->query,thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index d5034644830..74a4c80bfce 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -319,6 +319,8 @@ int mysql_update(THD *thd, mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { + if (error <= 0) + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, log_delayed); if (mysql_bin_log.write(&qinfo) && transactional_table) @@ -939,6 +941,8 @@ bool multi_update::send_eof() mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { + if (local_error <= 0) + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, log_delayed); if (mysql_bin_log.write(&qinfo) && trans_safe)