diff options
author | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2018-03-05 00:55:59 +0530 |
---|---|---|
committer | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2018-03-05 00:55:59 +0530 |
commit | e7fd141786daae620693351b17e1f7d0b644c334 (patch) | |
tree | 7e77170aadcce9ece8718f41575c5834800a0e4b | |
parent | d70573564cb2701076083ea7f55ae9539fad13b4 (diff) | |
download | mariadb-git-bb-10.3-mdev15443.tar.gz |
MDEV-15443 Invalid wsrep XID read from the rollback segmentbb-10.3-mdev15443
Problem:
=======
Transaction with disabled wsrep_on variable stores only transaction id
in the rollback segment and it doesn't write any XID information in rollback
segment. While reading the latest wsrep checkpoint from InnoDB, it reads
the undefined wsrep xid from the rollback segment which has maximum transaction
id.
Solution:
=========
- Introduce new field TRX_RSEG_WSREP_XID_SEQNO in rollback segment header page
which keeps track of the latest wsrep information. Basically it stores
trx->no whenever the trasaction with wsrep_on variable is enabled.
- To fetch the latest binlog information, InnoDB compares the binlog filename
and binlog offset.
-rw-r--r-- | mysql-test/suite/galera/r/galera_wsrep_xid.result | 14 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/galera_wsrep_xid.test | 33 | ||||
-rw-r--r-- | storage/innobase/include/trx0rseg.h | 11 | ||||
-rw-r--r-- | storage/innobase/trx/trx0rseg.cc | 55 |
4 files changed, 92 insertions, 21 deletions
diff --git a/mysql-test/suite/galera/r/galera_wsrep_xid.result b/mysql-test/suite/galera/r/galera_wsrep_xid.result new file mode 100644 index 00000000000..683ef362f6a --- /dev/null +++ b/mysql-test/suite/galera/r/galera_wsrep_xid.result @@ -0,0 +1,14 @@ +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +connection node_2; +SELECT * FROM t1; +f1 +1 +SET SESSION wsrep_on=0; +INSERT INTO t1 VALUES (2); +DELETE FROM t1 WHERE f1 = 2; +connection node_1; +INSERT INTO t1 VALUES (2); +connection node_2; +connection node_1; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_wsrep_xid.test b/mysql-test/suite/galera/t/galera_wsrep_xid.test new file mode 100644 index 00000000000..bbf582aa96c --- /dev/null +++ b/mysql-test/suite/galera/t/galera_wsrep_xid.test @@ -0,0 +1,33 @@ +--source include/have_innodb.inc +--source include/galera_cluster.inc + +# Initialize table on node_1 +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +# Go to node_2, verify that the previous INSERT completed. +# Take node_2 out of the cluster, insert and delete a record +# on a table with wsrep_on. +--connection node_2 +SELECT * FROM t1; +SET SESSION wsrep_on=0; +INSERT INTO t1 VALUES (2); +DELETE FROM t1 WHERE f1 = 2; + +# Shutdown node_2 +--source include/shutdown_mysqld.inc + +# On node_1, verify that the node has left the cluster. +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +# Insert into t1 to enforce IST on node_2 when it is restarted. +INSERT INTO t1 VALUES (2); + +# Restart node_2 +--connection node_2 +--source include/start_mysqld.inc + +--connection node_1 +DROP TABLE t1; diff --git a/storage/innobase/include/trx0rseg.h b/storage/innobase/include/trx0rseg.h index d68ece39911..f57b8e7fa06 100644 --- a/storage/innobase/include/trx0rseg.h +++ b/storage/innobase/include/trx0rseg.h @@ -245,15 +245,16 @@ If no binlog information is present, the first byte is NUL. */ #ifdef WITH_WSREP /** The offset to WSREP XID headers */ #define TRX_RSEG_WSREP_XID_INFO TRX_RSEG_MAX_TRX_ID + 16 + 512 - +/** Sequence number of WSREP XID. It is used to find latest WSREP XID info. */ +#define TRX_RSEG_WSREP_XID_SEQNO TRX_RSEG_WSREP_XID_INFO /** WSREP XID format (1 if present and valid, 0 if not present) */ -#define TRX_RSEG_WSREP_XID_FORMAT TRX_RSEG_WSREP_XID_INFO +#define TRX_RSEG_WSREP_XID_FORMAT TRX_RSEG_WSREP_XID_INFO + 8 /** WSREP XID GTRID length */ -#define TRX_RSEG_WSREP_XID_GTRID_LEN TRX_RSEG_WSREP_XID_INFO + 4 +#define TRX_RSEG_WSREP_XID_GTRID_LEN TRX_RSEG_WSREP_XID_INFO + 12 /** WSREP XID bqual length */ -#define TRX_RSEG_WSREP_XID_BQUAL_LEN TRX_RSEG_WSREP_XID_INFO + 8 +#define TRX_RSEG_WSREP_XID_BQUAL_LEN TRX_RSEG_WSREP_XID_INFO + 16 /** WSREP XID data (XIDDATASIZE bytes) */ -#define TRX_RSEG_WSREP_XID_DATA TRX_RSEG_WSREP_XID_INFO + 12 +#define TRX_RSEG_WSREP_XID_DATA TRX_RSEG_WSREP_XID_INFO + 20 #endif /* WITH_WSREP*/ /*-------------------------------------------------------------*/ diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index b9ca2481681..9932977f37b 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -83,6 +83,9 @@ trx_rseg_update_wsrep_checkpoint( trx_sys_cur_xid_seqno = xid_seqno; #endif /* UNIV_DEBUG */ + mlog_write_ull(TRX_RSEG_WSREP_XID_SEQNO + rseg_header, + trx_sys.get_max_trx_id(), mtr); + mlog_write_ulint(TRX_RSEG_WSREP_XID_FORMAT + rseg_header, uint32_t(xid->formatID), MLOG_4BYTES, mtr); @@ -209,7 +212,7 @@ bool trx_rseg_read_wsrep_checkpoint(XID& xid) } trx_id_t id = mach_read_from_8(rseg_header - + TRX_RSEG_MAX_TRX_ID); + + TRX_RSEG_WSREP_XID_SEQNO); if (id < max_id) { continue; @@ -398,44 +401,60 @@ trx_undo_lists_init(trx_rseg_t* rseg, trx_id_t& max_trx_id, } /** Restore the state of a persistent rollback segment. -@param[in,out] rseg persistent rollback segment -@param[in,out] max_trx_id maximum observed transaction identifier -@param[in,out] max_rseg_trx_id maximum observed TRX_RSEG_MAX_TRX_ID +@param[in,out] rseg persistent rollback segment +@param[in,out] max_trx_id maximum observed transaction identifier +@param[in,out] max_rseg_xid_seqno maximum observed sequence number for + WSREP XID info @param[in,out] mtr mini-transaction */ static void trx_rseg_mem_restore( trx_rseg_t* rseg, trx_id_t& max_trx_id, - trx_id_t& max_rseg_trx_id, +#ifdef WITH_WSREP + trx_id_t& max_rseg_xid_seqno, +#endif mtr_t* mtr) { trx_rsegf_t* rseg_header = trx_rsegf_get_new( rseg->space, rseg->page_no, mtr); + lint binlog_offset; if (mach_read_from_4(rseg_header + TRX_RSEG_FORMAT) == 0) { trx_id_t id = mach_read_from_8(rseg_header + TRX_RSEG_MAX_TRX_ID); - +#ifdef WITH_WSREP + trx_id_t xid_seqno = mach_read_from_8(rseg_header + + TRX_RSEG_WSREP_XID_SEQNO); +#endif /* WITH_WSRSEP */ if (id > max_trx_id) { max_trx_id = id; } - if (id > max_rseg_trx_id) { - max_rseg_trx_id = id; + if (rseg_header[TRX_RSEG_BINLOG_NAME]) { + + binlog_offset = mach_read_from_8( + rseg_header + TRX_RSEG_BINLOG_OFFSET); + + if (strncmp((char*) rseg_header + TRX_RSEG_BINLOG_NAME, + trx_sys.recovered_binlog_filename, + TRX_RSEG_BINLOG_NAME_LEN) >= 0 + && (trx_sys.recovered_binlog_offset + < binlog_offset)) { - if (rseg_header[TRX_RSEG_BINLOG_NAME]) { memcpy(trx_sys.recovered_binlog_filename, rseg_header + TRX_RSEG_BINLOG_NAME, TRX_RSEG_BINLOG_NAME_LEN); - trx_sys.recovered_binlog_offset = mach_read_from_8( - rseg_header - + TRX_RSEG_BINLOG_OFFSET); + trx_sys.recovered_binlog_offset = + binlog_offset; } #ifdef WITH_WSREP - trx_rseg_read_wsrep_checkpoint( - rseg_header, trx_sys.recovered_wsrep_xid); + if (xid_seqno > max_rseg_xid_seqno) { + max_rseg_xid_seqno = xid_seqno; + trx_rseg_read_wsrep_checkpoint( + rseg_header, trx_sys.recovered_wsrep_xid); + } #endif } } @@ -513,11 +532,12 @@ static void trx_rseg_init_binlog_info(const page_t* page) void trx_rseg_array_init() { - trx_id_t max_trx_id = 0, max_rseg_trx_id = 0; + trx_id_t max_trx_id = 0; *trx_sys.recovered_binlog_filename = '\0'; trx_sys.recovered_binlog_offset = -1; #ifdef WITH_WSREP + trx_id_t max_rseg_xid_seqno = 0; memset(&trx_sys.recovered_wsrep_xid, 0, sizeof trx_sys.recovered_wsrep_xid); trx_sys.recovered_wsrep_xid.formatID = -1; @@ -549,7 +569,10 @@ trx_rseg_array_init() ut_ad(!trx_sys.rseg_array[rseg_id]); trx_sys.rseg_array[rseg_id] = rseg; trx_rseg_mem_restore( - rseg, max_trx_id, max_rseg_trx_id, + rseg, max_trx_id, +#ifdef WITH_WSREP + max_rseg_xid_seqno, +#endif &mtr); } } |