Commit 55a7159f authored by unknown's avatar unknown

MDEV-4982: GTID looses all binlog state after crash if InnoDB is disabled

MDEV-4725: Incorrect binlog state recovery if crash while writing event group

The binlog state was not recovered correctly if XA is not used (eg. InnoDB
disabled), or if server crashed in the middle of writing an event group to the
binlog.

With this patch, we ensure that recovery of binlog state is done even if we do
not do the full XA binlog recovery, and we ensure that we only recover fully
written event groups into the binlog state.
parent 146c8a48
...@@ -90,5 +90,12 @@ a ...@@ -90,5 +90,12 @@ a
6 6
7 7
8 8
*** MDEV-4725: Incorrect recovery when crash in the middle of writing an event group ***
SET GLOBAL debug_dbug="+d,crash_before_writing_xid";
INSERT INTO t1 VALUES (9), (10);
SHOW VARIABLES like 'gtid_strict_mode';
Variable_name Value
gtid_strict_mode ON
include/start_slave.inc
DROP TABLE t1; DROP TABLE t1;
include/rpl_end.inc include/rpl_end.inc
include/rpl_init.inc [topology=1->2]
*** Test crashing master with InnoDB disabled, the binlog gtid state should still be correctly recovered. ***
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=MyISAM;
include/stop_slave.inc
CHANGE MASTER TO master_use_gtid=slave_pos;
include/start_slave.inc
INSERT INTO t1 VALUES (1);
INSERT INTO t1 VALUES (2);
SELECT * FROM t1 ORDER BY a;
a
1
2
FLUSH TABLES;
SET SESSION debug_dbug="+d,crash_dispatch_command_before";
SELECT 1;
Got one of the listed errors
INSERT INTO t1 VALUES (3);
SELECT * FROM t1 ORDER BY a;
a
1
2
3
DROP TABLE t1;
include/rpl_end.inc
...@@ -256,6 +256,43 @@ EOF ...@@ -256,6 +256,43 @@ EOF
SELECT * FROM t1 ORDER BY a; SELECT * FROM t1 ORDER BY a;
--echo *** MDEV-4725: Incorrect recovery when crash in the middle of writing an event group ***
--connection server_2
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
wait
EOF
--let $old_gtid_strict= `SELECT @@gtid_strict_mode`
SET GLOBAL debug_dbug="+d,crash_before_writing_xid";
--connection server_1
INSERT INTO t1 VALUES (9), (10);
--save_master_pos
--connection server_2
--source include/wait_until_disconnected.inc
# The bug was that during crash recovery we would update the binlog state
# with the GTID of the half-written event group at the end of the slaves
# binlog, even though this event group was not committed.
# We restart the server with gtid_strict_mode; this way, we get an error
# about duplicate gtid when the slave re-executes the event group, if the
# binlog crash recovery is incorrect.
--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
restart: --gtid_strict_mode=1
EOF
--enable_reconnect
--source include/wait_until_connected_again.inc
SHOW VARIABLES like 'gtid_strict_mode';
--source include/start_slave.inc
--sync_with_master
--disable_query_log
eval SET GLOBAL gtid_strict_mode= $old_gtid_strict;
--enable_query_log
--connection server_1 --connection server_1
DROP TABLE t1; DROP TABLE t1;
......
--skip-stack-trace --skip-core-file --skip-innodb
--source include/have_debug.inc
# Valgrind does not work well with test that crashes the server
--source include/not_valgrind.inc
--let $rpl_topology=1->2
--source include/rpl_init.inc
--echo *** Test crashing master with InnoDB disabled, the binlog gtid state should still be correctly recovered. ***
--connection server_1
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=MyISAM;
--save_master_pos
--connection server_2
--sync_with_master
--source include/stop_slave.inc
CHANGE MASTER TO master_use_gtid=slave_pos;
--source include/start_slave.inc
--connection server_1
INSERT INTO t1 VALUES (1);
INSERT INTO t1 VALUES (2);
--save_master_pos
--connection server_2
--sync_with_master
SELECT * FROM t1 ORDER BY a;
--connection server_1
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
wait
EOF
FLUSH TABLES;
SET SESSION debug_dbug="+d,crash_dispatch_command_before";
--error 2006,2013
SELECT 1;
--source include/wait_until_disconnected.inc
--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
restart-rpl_gtid_crash.test
EOF
--connection server_1
--enable_reconnect
--source include/wait_until_connected_again.inc
INSERT INTO t1 VALUES (3);
--save_master_pos
--connection server_2
--sync_with_master
SELECT * FROM t1 ORDER BY a;
--connection server_1
DROP TABLE t1;
--connection default
--enable_reconnect
--source include/wait_until_connected_again.inc
--source include/rpl_end.inc
This diff is collapsed.
...@@ -521,8 +521,8 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG ...@@ -521,8 +521,8 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
*/ */
uint *sync_period_ptr; uint *sync_period_ptr;
uint sync_counter; uint sync_counter;
/* Protect against reading the binlog state file twice. */ bool state_file_deleted;
bool state_read; bool binlog_state_recover_done;
inline uint get_sync_period() inline uint get_sync_period()
{ {
...@@ -661,7 +661,8 @@ public: ...@@ -661,7 +661,8 @@ public:
int unlog(ulong cookie, my_xid xid); int unlog(ulong cookie, my_xid xid);
void commit_checkpoint_notify(void *cookie); void commit_checkpoint_notify(void *cookie);
int recover(LOG_INFO *linfo, const char *last_log_name, IO_CACHE *first_log, int recover(LOG_INFO *linfo, const char *last_log_name, IO_CACHE *first_log,
Format_description_log_event *fdle); Format_description_log_event *fdle, bool do_xa);
int do_binlog_recovery(const char *opt_name, bool do_xa_recovery);
#if !defined(MYSQL_CLIENT) #if !defined(MYSQL_CLIENT)
int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event, int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event,
......
...@@ -5988,10 +5988,9 @@ static Log_event* next_event(rpl_group_info *rgi, ulonglong *event_size) ...@@ -5988,10 +5988,9 @@ static Log_event* next_event(rpl_group_info *rgi, ulonglong *event_size)
IO_CACHE* cur_log = rli->cur_log; IO_CACHE* cur_log = rli->cur_log;
mysql_mutex_t *log_lock = rli->relay_log.get_log_lock(); mysql_mutex_t *log_lock = rli->relay_log.get_log_lock();
const char* errmsg=0; const char* errmsg=0;
THD *thd = rgi->thd;
DBUG_ENTER("next_event"); DBUG_ENTER("next_event");
DBUG_ASSERT(thd != 0 && thd == rli->sql_driver_thd); DBUG_ASSERT(rgi->thd != 0 && rgi->thd == rli->sql_driver_thd);
*event_size= 0; *event_size= 0;
#ifndef DBUG_OFF #ifndef DBUG_OFF
......
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