Commit 675c22c0 authored by Andrei Elkin's avatar Andrei Elkin

MDEV-22757 Assertion !binlog || exist_hton_without_prepare' failed in...

MDEV-22757 Assertion !binlog || exist_hton_without_prepare' failed in MYSQL_BIN_LOG::unlog_xa_prepare

The assert fired falsely having not captured two more not apparent
possiblities in its condition.

They are masked out hton error out of REPLACE execution (so at later xa-prepare
that engine is still present as read-write) and a prepare-capable engine
which also may not be an actual participant in the xa transation. That
engine, such as SEQUENCE, though does create its own event block.
parent 0620ccf3
...@@ -29,3 +29,82 @@ master-bin.000001 # Query # # XA END X'33',X'',1 ...@@ -29,3 +29,82 @@ master-bin.000001 # Query # # XA END X'33',X'',1
master-bin.000001 # XA_prepare # # XA PREPARE X'33',X'',1 master-bin.000001 # XA_prepare # # XA PREPARE X'33',X'',1
master-bin.000001 # Gtid # # GTID #-#-# master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # XA ROLLBACK X'33',X'',1 master-bin.000001 # Query # # XA ROLLBACK X'33',X'',1
RESET MASTER;
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1),(2);
INSERT INTO t2 VALUES (1),(2);
XA START '1';
REPLACE INTO t1 SELECT * FROM t1;
REPLACE INTO t2 SELECT * FROM t2;
XA END '1';
XA PREPARE '1';
XA ROLLBACK '1';
Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back
DROP TABLE t1, t2;
# Proof of correct logging incl empty XA-PREPARE
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT) ENGINE=MyISAM
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1),(2)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO t2 VALUES (1),(2)
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Annotate_rows # # REPLACE INTO t1 SELECT * FROM t1
master-bin.000001 # Table_map # # table_id: # (test.t1)
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # XA START X'31',X'',1 GTID #-#-#
master-bin.000001 # Query # # XA END X'31',X'',1
master-bin.000001 # XA_prepare # # XA PREPARE X'31',X'',1
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # XA ROLLBACK X'31',X'',1
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; DROP TABLE `t1`,`t2` /* generated by server */
RESET MASTER;
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
CREATE SEQUENCE s ENGINE=InnoDB;
XA START '2';
SELECT NEXT VALUE FOR s;
NEXT VALUE FOR s
1
REPLACE INTO t1 SELECT * FROM t1;
XA END '2';
XA PREPARE '2';
XA ROLLBACK '2';
DROP SEQUENCE s;
DROP TABLE t1;
# Proof of correct logging incl empty XA-PREPARE
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Annotate_rows # # INSERT INTO t1 VALUES (1)
master-bin.000001 # Table_map # # table_id: # (test.t1)
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; CREATE SEQUENCE s ENGINE=InnoDB
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Annotate_rows # # SELECT NEXT VALUE FOR s
master-bin.000001 # Table_map # # table_id: # (test.s)
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # XA START X'32',X'',1 GTID #-#-#
master-bin.000001 # Query # # XA END X'32',X'',1
master-bin.000001 # XA_prepare # # XA PREPARE X'32',X'',1
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # XA ROLLBACK X'32',X'',1
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; DROP SEQUENCE `s` /* generated by server */
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
...@@ -33,3 +33,50 @@ XA ROLLBACK '3'; ...@@ -33,3 +33,50 @@ XA ROLLBACK '3';
--echo # Proof of correct logging incl empty XA-PREPARE --echo # Proof of correct logging incl empty XA-PREPARE
--source include/show_binlog_events.inc --source include/show_binlog_events.inc
# The test verifies execution and binary logging of user XA that produce empty
# XA-PREPARE group of events.
#
# MDEV-22757 Assertion `!binlog || exist_hton_without_prepare'
# in MYSQL_BIN_LOG::unlog_xa_prepare
RESET MASTER;
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1),(2);
INSERT INTO t2 VALUES (1),(2);
XA START '1';
REPLACE INTO t1 SELECT * FROM t1;
REPLACE INTO t2 SELECT * FROM t2;
XA END '1';
XA PREPARE '1';
# Cleanup
XA ROLLBACK '1';
DROP TABLE t1, t2;
--echo # Proof of correct logging incl empty XA-PREPARE
--source include/show_binlog_events.inc
# MDEV-22430 Assertion ... in MYSQL_BIN_LOG::unlog_xa_prepare
RESET MASTER;
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
CREATE SEQUENCE s ENGINE=InnoDB;
XA START '2';
SELECT NEXT VALUE FOR s;
REPLACE INTO t1 SELECT * FROM t1;
XA END '2';
XA PREPARE '2';
# Cleanup
XA ROLLBACK '2';
DROP SEQUENCE s;
DROP TABLE t1;
--echo # Proof of correct logging incl empty XA-PREPARE
--source include/show_binlog_events.inc
...@@ -10218,28 +10218,13 @@ int TC_LOG_BINLOG::unlog_xa_prepare(THD *thd, bool all) ...@@ -10218,28 +10218,13 @@ int TC_LOG_BINLOG::unlog_xa_prepare(THD *thd, bool all)
uint rw_count= ha_count_rw_all(thd, &ha_info); uint rw_count= ha_count_rw_all(thd, &ha_info);
bool rc= false; bool rc= false;
#ifndef DBUG_OFF /*
if (rw_count > 1) This transaction has not been binlogged as indicated by need_unlog.
{ Such exceptional cases include transactions with no effect to engines,
/* e.g REPLACE that does not change the dat but still the Engine
There must be no binlog_hton used in a transaction consisting of more transaction branch claims to be rw, and few more.
than 1 engine, *when* (at this point) this transaction has not been In all such cases an empty XA-prepare group of events is bin-logged.
binlogged. The one exception is if there is an engine without a */
prepare method, as in this case the engine doesn't support XA and
we have to ignore this check.
*/
bool binlog= false, exist_hton_without_prepare= false;
for (ha_info= thd->transaction->all.ha_list; ha_info;
ha_info= ha_info->next())
{
if (ha_info->ht() == binlog_hton)
binlog= true;
if (!ha_info->ht()->prepare)
exist_hton_without_prepare= true;
}
DBUG_ASSERT(!binlog || exist_hton_without_prepare);
}
#endif
if (rw_count > 0) if (rw_count > 0)
{ {
/* an empty XA-prepare event group is logged */ /* an empty XA-prepare event group is logged */
......
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