Implement variable legacy_xa_rollback_at_disconnect to support backwards compatibility for applications that rely on the pre-10.5 behavior for connection disconnect, which is to rollback the transaction (in violation of the XA specification). Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org> --- mysql-test/main/mysqld--help.result | 8 +++++++ mysql-test/main/xa.result | 16 +++++++++++++ mysql-test/main/xa.test | 19 +++++++++++++++ mysql-test/suite/rpl/r/rpl_xa.result | 24 +++++++++++++++++++ .../rpl/r/rpl_xa_gtid_pos_auto_engine.result | 24 +++++++++++++++++++ mysql-test/suite/rpl/t/rpl_xa.inc | 23 ++++++++++++++++++ .../sys_vars/r/sysvars_server_embedded.result | 10 ++++++++ .../r/sysvars_server_notembedded.result | 10 ++++++++ sql/sql_class.cc | 7 +++++- sql/sql_class.h | 1 + sql/sys_vars.cc | 10 ++++++++ sql/xa.h | 1 + 12 files changed, 152 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result index 1a2a740cb77..ac5ab0a88b1 100644 --- a/mysql-test/main/mysqld--help.result +++ b/mysql-test/main/mysqld--help.result @@ -433,6 +433,13 @@ The following specify which files/extra groups are read (specified before remain --lc-time-names=name Set the language used for the month names and the days of the week. + --legacy-xa-rollback-at-disconnect + If a user session disconnects after putting a transaction + into the XA PREPAREd state, roll back the transaction. + Can be used for backwards compatibility to enable this + pre-10.5 behavior for applications that expect it. Note + that this violates the XA specification and should not be + used for new code --local-infile Enable LOAD DATA LOCAL INFILE (Defaults to on; use --skip-local-infile to disable.) --lock-wait-timeout=# @@ -1566,6 +1573,7 @@ large-pages FALSE lc-messages en_US lc-messages-dir MYSQL_SHAREDIR/ lc-time-names en_US +legacy-xa-rollback-at-disconnect FALSE local-infile TRUE lock-wait-timeout 86400 log-bin foo diff --git a/mysql-test/main/xa.result b/mysql-test/main/xa.result index faabf1cf695..58ad2a54edd 100644 --- a/mysql-test/main/xa.result +++ b/mysql-test/main/xa.result @@ -592,6 +592,22 @@ formatID gtrid_length bqual_length data xa rollback '4'; ERROR XA100: XA_RBROLLBACK: Transaction branch was rolled back set @@global.read_only=@sav_read_only; +# MDEV-35019: Provide a way to enable "rollback XA on disconnect" behavior we had before 10.5.2 +# Test legacy_xa_rollback_at_disconnect option. +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 0); +connect con1,localhost,root,,; +SET SESSION legacy_xa_rollback_at_disconnect= 1; +XA START '5'; +INSERT INTO t1 VALUES (2, 0); +XA END '5'; +XA PREPARE '5'; +disconnect con1; +connection default; +INSERT INTO t1 VALUES (3, 0); +XA ROLLBACK '5'; +ERROR XAE04: XAER_NOTA: Unknown XID +DROP TABLE t1; # # End of 10.5 tests # diff --git a/mysql-test/main/xa.test b/mysql-test/main/xa.test index e1ca39be9ab..dfc97002168 100644 --- a/mysql-test/main/xa.test +++ b/mysql-test/main/xa.test @@ -747,6 +747,25 @@ xa rollback '4'; set @@global.read_only=@sav_read_only; +--echo # MDEV-35019: Provide a way to enable "rollback XA on disconnect" behavior we had before 10.5.2 +--echo # Test legacy_xa_rollback_at_disconnect option. +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 0); +connect (con1,localhost,root,,); +SET SESSION legacy_xa_rollback_at_disconnect= 1; +XA START '5'; +INSERT INTO t1 VALUES (2, 0); +XA END '5'; +XA PREPARE '5'; +disconnect con1; + +connection default; +--source include/wait_until_count_sessions.inc +INSERT INTO t1 VALUES (3, 0); +--error ER_XAER_NOTA +XA ROLLBACK '5'; +DROP TABLE t1; + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/suite/rpl/r/rpl_xa.result b/mysql-test/suite/rpl/r/rpl_xa.result index 061c7b360d0..7b58d3d6e06 100644 --- a/mysql-test/suite/rpl/r/rpl_xa.result +++ b/mysql-test/suite/rpl/r/rpl_xa.result @@ -280,4 +280,28 @@ disconnect con1; connection master; xa commit '1'; drop table t2, t1; +# MDEV-35019 Provide a way to enable "rollback XA on disconnect" behavior we had before 10.5.2 +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1), (3); +connect con1, localhost,root; +SET SESSION legacy_xa_rollback_at_disconnect= 1; +XA START '3'; +INSERT INTO t1 VALUES (2); +XA END '3'; +XA PREPARE '3'; +disconnect con1; +connection master; +include/save_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +a +1 +3 +connection slave; +include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +a +1 +3 +connection master; +DROP TABLE t1; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_xa_gtid_pos_auto_engine.result b/mysql-test/suite/rpl/r/rpl_xa_gtid_pos_auto_engine.result index 35625cc7026..2cb9b6c4290 100644 --- a/mysql-test/suite/rpl/r/rpl_xa_gtid_pos_auto_engine.result +++ b/mysql-test/suite/rpl/r/rpl_xa_gtid_pos_auto_engine.result @@ -289,6 +289,30 @@ disconnect con1; connection master; xa commit '1'; drop table t2, t1; +# MDEV-35019 Provide a way to enable "rollback XA on disconnect" behavior we had before 10.5.2 +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1), (3); +connect con1, localhost,root; +SET SESSION legacy_xa_rollback_at_disconnect= 1; +XA START '3'; +INSERT INTO t1 VALUES (2); +XA END '3'; +XA PREPARE '3'; +disconnect con1; +connection master; +include/save_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +a +1 +3 +connection slave; +include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +a +1 +3 +connection master; +DROP TABLE t1; connection slave; include/stop_slave.inc SET @@global.gtid_pos_auto_engines=""; diff --git a/mysql-test/suite/rpl/t/rpl_xa.inc b/mysql-test/suite/rpl/t/rpl_xa.inc index d22d2d2ef3d..050b9597ccc 100644 --- a/mysql-test/suite/rpl/t/rpl_xa.inc +++ b/mysql-test/suite/rpl/t/rpl_xa.inc @@ -431,3 +431,26 @@ disconnect con1; connection master; xa commit '1'; drop table t2, t1; + +--echo # MDEV-35019 Provide a way to enable "rollback XA on disconnect" behavior we had before 10.5.2 +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1), (3); + +connect con1, localhost,root; +SET SESSION legacy_xa_rollback_at_disconnect= 1; +XA START '3'; +INSERT INTO t1 VALUES (2); +XA END '3'; +XA PREPARE '3'; +--disconnect con1 + +--connection master +--source include/save_master_gtid.inc +SELECT * FROM t1 ORDER BY a; + +--connection slave +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; + +--connection master +DROP TABLE t1; diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index fcd1ee9a141..d45ab7f80c8 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -1532,6 +1532,16 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME LEGACY_XA_ROLLBACK_AT_DISCONNECT +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT If a user session disconnects after putting a transaction into the XA PREPAREd state, roll back the transaction. Can be used for backwards compatibility to enable this pre-10.5 behavior for applications that expect it. Note that this violates the XA specification and should not be used for new code +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME LICENSE VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 1d5e9499c7a..73e853f12a5 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -1642,6 +1642,16 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME LEGACY_XA_ROLLBACK_AT_DISCONNECT +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT If a user session disconnects after putting a transaction into the XA PREPAREd state, roll back the transaction. Can be used for backwards compatibility to enable this pre-10.5 behavior for applications that expect it. Note that this violates the XA specification and should not be used for new code +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME LICENSE VARIABLE_SCOPE GLOBAL VARIABLE_TYPE VARCHAR diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 7913f1a40d2..cd0418553fa 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1552,7 +1552,12 @@ void THD::cleanup(void) close_temporary_tables(); if (transaction->xid_state.is_explicit_XA()) - trans_xa_detach(this); + { + if (unlikely(variables.legacy_xa_rollback_at_disconnect)) + xa_trans_force_rollback(this); + else + trans_xa_detach(this); + } else trans_rollback(this); diff --git a/sql/sql_class.h b/sql/sql_class.h index 7e5d9ac96e3..c0e304dd95f 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -846,6 +846,7 @@ typedef struct system_variables uint in_subquery_conversion_threshold; ulong optimizer_max_sel_arg_weight; ulonglong max_rowid_filter_size; + my_bool legacy_xa_rollback_at_disconnect; vers_asof_timestamp_t vers_asof_timestamp; ulong vers_alter_history; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 9a4180ae000..18374544126 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -6761,3 +6761,13 @@ static Sys_var_ulonglong Sys_max_rowid_filter_size( SESSION_VAR(max_rowid_filter_size), CMD_LINE(REQUIRED_ARG), VALID_RANGE(1024, (ulonglong)~(intptr)0), DEFAULT(128*1024), BLOCK_SIZE(1)); + +static Sys_var_mybool Sys_legacy_xa_rollback_at_disconnect( + "legacy_xa_rollback_at_disconnect", + "If a user session disconnects after putting a transaction into the XA " + "PREPAREd state, roll back the transaction. Can be used for backwards " + "compatibility to enable this pre-10.5 behavior for applications that " + "expect it. Note that this violates the XA specification and should not " + "be used for new code", + SESSION_VAR(legacy_xa_rollback_at_disconnect), CMD_LINE(OPT_ARG), + DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG); diff --git a/sql/xa.h b/sql/xa.h index 0b2d0696642..4260033d0fb 100644 --- a/sql/xa.h +++ b/sql/xa.h @@ -45,6 +45,7 @@ bool xid_cache_insert(XID *xid); bool xid_cache_insert(THD *thd, XID_STATE *xid_state, XID *xid); void xid_cache_delete(THD *thd, XID_STATE *xid_state); +bool xa_trans_force_rollback(THD *thd); bool trans_xa_start(THD *thd); bool trans_xa_end(THD *thd); bool trans_xa_prepare(THD *thd); -- 2.39.2