Commit 39001478 authored by Andrei Elkin's avatar Andrei Elkin

MDEV-26031 unnessary xid logging in one phase commit case

The bug was originally observed as hanging binlog background thread at
shutdown similar to one of MDEV-21120.
It occurred through unnessary xid logging in 1pc execution.

Two parts of the issue are fixed.  Per engine loop by involved engine
with attempt to mark a group requiring xid unlogging gets corrected in
two ways. Do not execute it when the termination event is irrelevant
for recovery, does not have xid in particular.  Do not break the loop
anymore unconditionally at the end of the 1st iteration.
parent c29f45ce
RESET MASTER;
CREATE TABLE t (f INT) ENGINE=INNODB;
CREATE TABLE ta (f INT) ENGINE=Aria;
BEGIN;
INSERT INTO t SET f = 1;
INSERT INTO ta SET f = 1;
COMMIT;
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO ta SET f = 1
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO t SET f = 1
master-bin.000001 # Query # # COMMIT
# Prove that binlog is resettable. Under the bug condition it was not.
RESET MASTER;
SET @@binlog_format = ROW;
CREATE TABLE ta2 ENGINE = Aria SELECT * from t;
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; CREATE TABLE `ta2` (
`f` int(11) DEFAULT NULL
) ENGINE=Aria PAGE_CHECKSUM=1
master-bin.000001 # Annotate_rows # # CREATE TABLE ta2 ENGINE = Aria SELECT * from t
master-bin.000001 # Table_map # # table_id: # (test.ta2)
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # COMMIT
# Prove that binlog is resettable. Under the bug condition it was not.
RESET MASTER;
# Cleanup
DROP TABLE ta2, ta, t;
# End of the tests
# The test file contains tests specific to one phase commit
# execution and binlogging.
#
# MDEV-26031 unnessary xid logging in one phase commit case
#
--source include/have_innodb.inc
--source include/have_aria.inc
--source include/have_binlog_format_mixed.inc
RESET MASTER;
CREATE TABLE t (f INT) ENGINE=INNODB;
CREATE TABLE ta (f INT) ENGINE=Aria;
--let $binlog_start = query_get_value(SHOW MASTER STATUS, Position, 1)
BEGIN;
INSERT INTO t SET f = 1;
INSERT INTO ta SET f = 1;
COMMIT;
--let $binlog_file = query_get_value(SHOW MASTER STATUS, File, 1)
--source include/show_binlog_events.inc
--echo # Prove that binlog is resettable. Under the bug condition it was not.
RESET MASTER;
--let $binlog_start = query_get_value(SHOW MASTER STATUS, Position, 1)
--let $binlog_file = query_get_value(SHOW MASTER STATUS, File, 1)
SET @@binlog_format = ROW;
CREATE TABLE ta2 ENGINE = Aria SELECT * from t;
--source include/show_binlog_events.inc
--echo # Prove that binlog is resettable. Under the bug condition it was not.
RESET MASTER;
--echo # Cleanup
DROP TABLE ta2, ta, t;
--echo # End of the tests
...@@ -2186,11 +2186,20 @@ int binlog_commit(THD *thd, bool all, bool ro_1pc) ...@@ -2186,11 +2186,20 @@ int binlog_commit(THD *thd, bool all, bool ro_1pc)
*/ */
if (likely(!error) && ending_trans(thd, all)) if (likely(!error) && ending_trans(thd, all))
{ {
error= is_preparing_xa(thd) ? bool is_xa_prepare= is_preparing_xa(thd);
error= is_xa_prepare ?
binlog_commit_flush_xa_prepare(thd, all, cache_mngr) : binlog_commit_flush_xa_prepare(thd, all, cache_mngr) :
binlog_commit_flush_trx_cache (thd, all, cache_mngr, ro_1pc); binlog_commit_flush_trx_cache (thd, all, cache_mngr, ro_1pc);
// the user xa is unlogged on common exec path with the "empty" xa case
if (cache_mngr->need_unlog && !is_xa_prepare)
{
error=
mysql_bin_log.unlog(BINLOG_COOKIE_MAKE(cache_mngr->binlog_id,
cache_mngr->delayed_error), 1);
cache_mngr->need_unlog= false;
}
} }
/* /*
This is part of the stmt rollback. This is part of the stmt rollback.
*/ */
...@@ -7634,16 +7643,16 @@ MYSQL_BIN_LOG::write_transaction_to_binlog(THD *thd, ...@@ -7634,16 +7643,16 @@ MYSQL_BIN_LOG::write_transaction_to_binlog(THD *thd,
entry.need_unlog= is_preparing_xa(thd); entry.need_unlog= is_preparing_xa(thd);
ha_info= all ? thd->transaction->all.ha_list : thd->transaction->stmt.ha_list; ha_info= all ? thd->transaction->all.ha_list : thd->transaction->stmt.ha_list;
entry.ro_1pc= is_ro_1pc; entry.ro_1pc= is_ro_1pc;
entry.end_event= end_ev;
auto has_xid= entry.end_event->get_type_code() == XID_EVENT;
for (; !entry.need_unlog && ha_info; ha_info= ha_info->next()) for (; has_xid && !entry.need_unlog && ha_info; ha_info= ha_info->next())
{ {
if (ha_info->is_started() && ha_info->ht() != binlog_hton && if (ha_info->is_started() && ha_info->ht() != binlog_hton &&
!ha_info->ht()->commit_checkpoint_request) !ha_info->ht()->commit_checkpoint_request)
entry.need_unlog= true; entry.need_unlog= true;
break;
} }
entry.end_event= end_ev;
if (cache_mngr->stmt_cache.has_incident() || if (cache_mngr->stmt_cache.has_incident() ||
cache_mngr->trx_cache.has_incident()) cache_mngr->trx_cache.has_incident())
{ {
......
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