mariadb/mysql-test/suite/galera/t/MDEV-15443.test
Marko Mäkelä 67f6d40bd9 MDEV-15443 Properly read wsrep XID and binlog position from rollback segment headers
The problem is a regression caused by MDEV-15158.
If some transactions were committed with wsrep_on=0, a
rollback segment header having the highest trx_id assigned might
store undefined wsrep XID. When reading the wsrep checkpoint
from InnodB, the undefined wsrep XID might be returned instead
of the highest valid one.

Similarly, if the binary log is intermittently disabled or enabled
while InnoDB transactions are being committed, the latest updated
rollback segment header page might not contain the latest binlog metadata.

Therefore, the MDEV-15158 logic to rely on TRX_RSEG_MAX_TRX_ID for
determining the most recent WSREP XID or binlog position is invalid.
We must choose the maximum entries among the rollback segment header
pages.

This fix is based on code submitted by Teemu Ollakka from Codership
and by Thirunarayanan Balathandayuthapani from MariaDB Corporation.

trx_purge_add_undo_to_history(): Only write TRX_RSEG_MAX_TRX_ID
when it was used to be written before MDEV-15158.

wsrep_seqno: Renamed from trx_sys_cur_xid_seqno.

wsrep_uuid: Renamed from trx_sys_cur_xid_uuid, and enable in non-debug
builds.

read_wsrep_xid_uuid(): Make non-debug, and remove the memcpy().

trx_rseg_update_wsrep_checkpoint(): Correctly compare and copy
the entire UUID in the debug check. In case of UUID mismatch,
write the WSREP XID to all 128 rollback segment headers in
a single mini-transaction.

trx_rseg_read_wsrep_checkpoint(rseg_header, xid): Make static.
In case the information is absent, do not overwrite xid.

trx_rseg_read_wsrep_checkpoint(xid): Determine the maximum
WSREP XID.

trx_rseg_mem_restore(): Remove the parameter max_rseg_trx_id.
Determine the latest binlog file and position by comparing
file names and offsets. Declare trx_sys.recovered_binlog_offset
as an unsigned type.
2018-03-06 23:32:26 +02:00

53 lines
1.7 KiB
Text

#
# MDEV-15443
#
# If transactions are executed into InnoDB without wsrep_on,
# rseg header trx_id gets incremented and the rseg header
# corresponding to maximum trx_id may store undefined wsrep XID.
# When the wsrep XID is read from the storage engine,
# undefined XID may returned instead the valid one.
#
# This test demonstrates the problem by taking a node_2 out
# of the cluster and writing and deleting a row with
# wsrep_on=0. When the bug is present, node_2 will fail to
# rejoin the cluster because an invalid XID is read from the
# storage engine after startup/recovery.
#
--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 GLOBAL wsrep_cluster_address='';
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
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--source include/wait_condition.inc
--connection node_1
--source include/wait_condition.inc
DROP TABLE t1;