summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <knielsen@knielsen-hq.org>2013-03-21 17:33:29 +0100
committerunknown <knielsen@knielsen-hq.org>2013-03-21 17:33:29 +0100
commitb6b84d68250ea13a1a90079120e303658465bfb7 (patch)
tree279e9d97c7df805c92ad319a826d08ae7b61387a
parente590f89114bd205e30488cb8b1433f645babc170 (diff)
downloadmariadb-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.result26
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test38
-rw-r--r--sql/log_event.cc50
-rw-r--r--sql/rpl_gtid.cc9
-rw-r--r--sql/rpl_rli.cc15
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, &gtid, 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, &gtid, 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, &gtid, 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