Commit b6b84d68 authored by unknown's avatar unknown

MDEV-26: Global transaction ID.

Fix error handling when record_gtid() fails to update the
mysql.rpl_slave_state table.
parent e590f891
......@@ -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
......@@ -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
......@@ -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;
}
}
......
......@@ -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;
}
......
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment