diff options
author | unknown <knielsen@knielsen-hq.org> | 2013-03-21 17:33:29 +0100 |
---|---|---|
committer | unknown <knielsen@knielsen-hq.org> | 2013-03-21 17:33:29 +0100 |
commit | b6b84d68250ea13a1a90079120e303658465bfb7 (patch) | |
tree | 279e9d97c7df805c92ad319a826d08ae7b61387a | |
parent | e590f89114bd205e30488cb8b1433f645babc170 (diff) | |
download | mariadb-git-b6b84d68250ea13a1a90079120e303658465bfb7.tar.gz |
MDEV-26: Global transaction ID.
Fix error handling when record_gtid() fails to update the
mysql.rpl_slave_state table.
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_gtid_errorhandling.result | 26 | ||||
-rw-r--r-- | mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test | 38 | ||||
-rw-r--r-- | sql/log_event.cc | 50 | ||||
-rw-r--r-- | sql/rpl_gtid.cc | 9 | ||||
-rw-r--r-- | sql/rpl_rli.cc | 15 |
5 files changed, 108 insertions, 30 deletions
diff --git a/mysql-test/suite/rpl/r/rpl_gtid_errorhandling.result b/mysql-test/suite/rpl/r/rpl_gtid_errorhandling.result index db6e2672a18..3ff6fe10e4a 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_errorhandling.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_errorhandling.result @@ -7,21 +7,21 @@ ALTER TABLE mysql.rpl_slave_state CHANGE seq_no seq_no VARCHAR(20); START SLAVE; INSERT INTO t1 VALUES (1); CALL mtr.add_suppression("Slave: Failed to open mysql.rpl_slave_state"); -include/wait_for_slave_sql_error.inc [errno=1943] +include/wait_for_slave_sql_error.inc [errno=1941] include/stop_slave.inc ALTER TABLE mysql.rpl_slave_state CHANGE seq_no seq_no BIGINT UNSIGNED NOT NULL; ALTER TABLE mysql.rpl_slave_state DROP PRIMARY KEY; ALTER TABLE mysql.rpl_slave_state ADD PRIMARY KEY (sub_id, domain_id); START SLAVE; -include/wait_for_slave_sql_error.inc [errno=1943] +include/wait_for_slave_sql_error.inc [errno=1941] include/stop_slave.inc ALTER TABLE mysql.rpl_slave_state DROP PRIMARY KEY; START SLAVE; -include/wait_for_slave_sql_error.inc [errno=1943] +include/wait_for_slave_sql_error.inc [errno=1941] include/stop_slave.inc ALTER TABLE mysql.rpl_slave_state ADD PRIMARY KEY (sub_id); START SLAVE; -include/wait_for_slave_sql_error.inc [errno=1943] +include/wait_for_slave_sql_error.inc [errno=1941] include/stop_slave.inc ALTER TABLE mysql.rpl_slave_state DROP PRIMARY KEY; ALTER TABLE mysql.rpl_slave_state ADD PRIMARY KEY (domain_id, sub_id); @@ -85,5 +85,23 @@ START SLAVE; SET sql_log_bin=0; CALL mtr.add_suppression("The slave I/O thread stops because master does not support MariaDB global transaction id"); SET sql_log_bin=1; +*** Test error during record_gtid() (non-xid cases) *** +include/stop_slave.inc +CREATE TABLE t2 (a INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1); +SET @old_dbug= @@global.DEBUG_DBUG; +SET GLOBAL debug_dbug="+d,gtid_inject_record_gtid"; +START SLAVE; +include/wait_for_slave_sql_error.inc [errno=1941] +SET GLOBAL debug_dbug= @old_dbug; +START SLAVE SQL_THREAD; +SELECT * FROM t2; +a +1 +1 +SET sql_log_bin=0; +CALL mtr.add_suppression("Slave: Could not update replication slave gtid state"); +SET sql_log_bin=1; DROP TABLE t1; +DROP TABLE t2; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test b/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test index ada6fa22490..0efdcd18d35 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test @@ -16,7 +16,7 @@ INSERT INTO t1 VALUES (1); --connection slave CALL mtr.add_suppression("Slave: Failed to open mysql.rpl_slave_state"); ---let $slave_sql_errno=1943 +--let $slave_sql_errno=1941 --source include/wait_for_slave_sql_error.inc --source include/stop_slave.inc @@ -24,19 +24,19 @@ ALTER TABLE mysql.rpl_slave_state CHANGE seq_no seq_no BIGINT UNSIGNED NOT NULL; ALTER TABLE mysql.rpl_slave_state DROP PRIMARY KEY; ALTER TABLE mysql.rpl_slave_state ADD PRIMARY KEY (sub_id, domain_id); START SLAVE; ---let $slave_sql_errno=1943 +--let $slave_sql_errno=1941 --source include/wait_for_slave_sql_error.inc --source include/stop_slave.inc ALTER TABLE mysql.rpl_slave_state DROP PRIMARY KEY; START SLAVE; ---let $slave_sql_errno=1943 +--let $slave_sql_errno=1941 --source include/wait_for_slave_sql_error.inc --source include/stop_slave.inc ALTER TABLE mysql.rpl_slave_state ADD PRIMARY KEY (sub_id); START SLAVE; ---let $slave_sql_errno=1943 +--let $slave_sql_errno=1941 --source include/wait_for_slave_sql_error.inc --source include/stop_slave.inc @@ -134,7 +134,37 @@ CALL mtr.add_suppression("The slave I/O thread stops because master does not sup SET sql_log_bin=1; +--echo *** Test error during record_gtid() (non-xid cases) *** + +--connection slave +--source include/stop_slave.inc + +--connection master +CREATE TABLE t2 (a INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1); +--save_master_pos + +--connection slave +SET @old_dbug= @@global.DEBUG_DBUG; +SET GLOBAL debug_dbug="+d,gtid_inject_record_gtid"; + +START SLAVE; +--let $slave_sql_errno= 1941 +--source include/wait_for_slave_sql_error.inc + +SET GLOBAL debug_dbug= @old_dbug; + +START SLAVE SQL_THREAD; +--sync_with_master + +SELECT * FROM t2; +SET sql_log_bin=0; +CALL mtr.add_suppression("Slave: Could not update replication slave gtid state"); +SET sql_log_bin=1; + + --connection master DROP TABLE t1; +DROP TABLE t2; --source include/rpl_end.inc diff --git a/sql/log_event.cc b/sql/log_event.cc index 1309907e91f..b083a6eb2a4 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3814,26 +3814,6 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli, */ const_cast<Relay_log_info*>(rli)->inc_event_relay_log_pos(); const_cast<Relay_log_info*>(rli)->clear_flag(Relay_log_info::IN_STMT); - - /* - Record any GTID in the same transaction, so slave state is - transactionally consistent. - */ - if ((sub_id= rli->gtid_sub_id)) - { - /* Clear the GTID from the RLI so we don't accidentally reuse it. */ - const_cast<Relay_log_info*>(rli)->gtid_sub_id= 0; - - gtid= rli->current_gtid; - error= rpl_global_gtid_slave_state.record_gtid(thd, >id, sub_id, true); - if (error) - { - my_error(ER_CANNOT_UPDATE_GTID_STATE, MYF(0)); - trans_rollback(thd); - sub_id= 0; - goto compare_errors; - } - } } else { @@ -3958,6 +3938,30 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli, else thd->variables.collation_database= thd->db_charset; + /* + Record any GTID in the same transaction, so slave state is + transactionally consistent. + */ + if (strcmp("COMMIT", query) == 0 && (sub_id= rli->gtid_sub_id)) + { + /* Clear the GTID from the RLI so we don't accidentally reuse it. */ + const_cast<Relay_log_info*>(rli)->gtid_sub_id= 0; + + gtid= rli->current_gtid; + if (rpl_global_gtid_slave_state.record_gtid(thd, >id, sub_id, true)) + { + rli->report(ERROR_LEVEL, ER_CANNOT_UPDATE_GTID_STATE, + "Error during COMMIT: failed to update GTID state in " + "%s.%s: %d: %s", + "mysql", rpl_gtid_slave_state_table_name.str, + thd->stmt_da->sql_errno(), thd->stmt_da->message()); + trans_rollback(thd); + sub_id= 0; + thd->is_slave_error= 1; + goto end; + } + } + thd->table_map_for_update= (table_map)table_map_for_update; thd->set_invoker(&user, &host); /* @@ -6842,7 +6846,13 @@ int Xid_log_event::do_apply_event(Relay_log_info const *rli) err= rpl_global_gtid_slave_state.record_gtid(thd, >id, sub_id, true); if (err) { + rli->report(ERROR_LEVEL, ER_CANNOT_UPDATE_GTID_STATE, + "Error during XID COMMIT: failed to update GTID state in " + "%s.%s: %d: %s", + "mysql", rpl_gtid_slave_state_table_name.str, + thd->stmt_da->sql_errno(), thd->stmt_da->message()); trans_rollback(thd); + thd->is_slave_error= 1; return err; } } diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index 6a57f7cdb9c..7f5aa0b780b 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -29,7 +29,7 @@ const LEX_STRING rpl_gtid_slave_state_table_name= - { STRING_WITH_LEN("rpl_slave_state") }; + { C_STRING_WITH_LEN("rpl_slave_state") }; void @@ -298,6 +298,12 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, mysql_reset_thd_for_next_command(thd, 0); + DBUG_EXECUTE_IF("gtid_inject_record_gtid", + { + my_error(ER_CANNOT_UPDATE_GTID_STATE, MYF(0)); + return 1; + } ); + tlist.init_one_table(STRING_WITH_LEN("mysql"), rpl_gtid_slave_state_table_name.str, rpl_gtid_slave_state_table_name.length, @@ -328,6 +334,7 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, if ((elem= get_element(gtid->domain_id)) == NULL) { unlock(); + my_error(ER_OUT_OF_RESOURCES, MYF(0)); err= 1; goto end; } diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 11249854c15..41bff96b5e5 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1232,7 +1232,20 @@ void Relay_log_info::stmt_done(my_off_t event_master_log_pos, else { inc_group_relay_log_pos(event_master_log_pos); - rpl_global_gtid_slave_state.record_and_update_gtid(thd, this); + if (rpl_global_gtid_slave_state.record_and_update_gtid(thd, this)) + { + report(WARNING_LEVEL, ER_CANNOT_UPDATE_GTID_STATE, + "Failed to update GTID state in %s.%s, slave state may become " + "inconsistent: %d: %s", + "mysql", rpl_gtid_slave_state_table_name.str, + thd->stmt_da->sql_errno(), thd->stmt_da->message()); + /* + At this point we are not in a transaction (for example after DDL), + so we can not roll back. Anyway, normally updates to the slave + state table should not fail, and if they do, at least we made the + DBA aware of the problem in the error log. + */ + } flush_relay_log_info(this); /* Note that Rotate_log_event::do_apply_event() does not call this |