mariadb/mysql-test/include/show_binlog_events2.inc
Andrei ca86986a14 MDEV-32830 I. refactor XA binlogging for better integration with BGC/replication/recovery
This commit is the part I of the series of four that addresses
MDEV-31949 in two main directions which are xa parallel slave
performance and xa transaction crash-recovery.

This one improves upon MDEV-742 design's XA binlogging to
facilitate to the crash-recovery (the actual binlog-based recovery
is coming in the part IV of MDEV-33168 et al).

With the refactoring changes, when binlog is ON, handling of execution of
a XA transaction, including binlogging, is made conceptually uniform
with the normal BEGIN-COMMIT transaction.
That is At XA-PREPARE the transaction first is prepared in engines and
after that accumulated replication events are written to the binary
log, naturally without any completion event as it's unknown yet.
When later XA-"COMPLETE" that is XA-COMMIT and XA-PREPARE follows up,
the binary logging of respective Query event takes place first.
One can perceive such scheme as if a normal transaction logging
is split in the middle into two parts (and nothing really happens
in between of them but time passed by). And after the second chunk is sent
to binlog the transaction gets committed (or rolled back) in engine.

With binlog is enabled both phases' loggings go through binlog-group-commit,
where XA-PREPARE "sub-transaction" merely groups for binary logging
so skips the engine action while XA-"COMPLETE" does both, that is the logging
and an ordered "complete". This behavior is also consistent between
completions from the native and external connections.
Being a participant of binlog-group-commit designates either XA phase
is recoverable (not implemented here) from active binlogs determined
by binlog-checkpoint.
For the latter specifically this patch removes custom unlogging of XA-prepare
group. See
   entry.need_unlog= 0
et al in MYSQL_BIN_LOG::write_transaction_to_binlog().

In addition to the above a corner case of engine read-only XA transaction
is addressed. Previously it was streamlined with logging an empty XA-PREPARE
group of binlog events concluded by XA-"COMPLETE" query-event.
Now when a preparing XA transaction is found to have only read-only engine
branches or none it is marked for rollback as XA_RDONLY optimization:
- nothing gets logged at the prepare time an XA_RDONLY note is generated and
- it's rolled back at disconnect
For XA-COMPLETE to tell whether the prepare phase was logged or
not the XID state object is extended with a boolean flag which is a
part internal interface for recovery implementation.
The flag is normally raised by XA-prepare at flushing to binlog and
also at binlog recovery (will be done so it's fully implemented).

Notable changes:

sql/handler.cc
  - ha_prepare()
    a. is ensured to execute binlog_hton::prepare() as
       the last XA's branch for preparing;
    b. engine read-only is marked in the xid state to rollback and
       ER_XA_RDONLY *note* is generated.
  - conversely ha_rollback_trans() executes binlog hton::rollback() as first
    branch (the commit method was already equipped to do so)
  - ditto to the external completion of XA via ha_commit_or_rollback_by_xid();
    the function is made a sort of recursive. It may be first be invoked
    on a top level to take on the binlog hton "completion" to be
    called from its stack once again now having is_xap_binlogged() false,
    so to carry out the engine commit.
  - xarecover_handlerton() now only simulates successful find of the user
    xid in binlog.
sql/log.cc
  - binlog_commit,rollback() et al are simplified and cleaned up (like
    binlog_complete_by_xid() introduction).

    In particular binlog_{commit,rollback}() are rendered to retain
    just a single piece of XA footprint in either. The methods recognize
    naturally empty transaction caches at XA completion to proceed anyway
    into binlog-group-commit thickness;
    the binlog_commit's binlog_commit_flush_trx_cache() decides which
    type of transaction and which XA phase is being handled so a proper
    group event closure is computed.
  - MYSQL_BIN_LOG::trx_group_commit_with_engines() takes care to
    raise or drop XID::binlogged flag via xid_cache_update_xa_binlog_state().
  - the new run_xa_complete_ordered() encapsulates XA specifics at
    execution of the engine ordered commit. It's defined with asserts due to
    MDEV-32455.
    It's not done as TC_LOG::member because of the scope of this work is
    limited. The new function mirrors the logic of the normal run_commit_ordered()
    in that it skips engine completion for those that lack
    hton::commit_ordered() in favor of doing that on the top level
    of ha_commit,rollback_trans().
sql/log_event_server.cc
  - use the transaction cache at XA-PREPARE handling (specifically
    when XA-END Query event is logged).
sql/xa.cc
  - XID_cache_element extended with is-binlogged meaning flag and
    few rating functions added to use by binlogging and recovery
    (xid_cache_update_xa_binlog_state());
  - trans_xa_commit,rollback() external action branches are converted
    into calls of a new largely common function.
sql/xa.h
  - xid_cache_insert(XID *xid, bool is_binlogged) parameter list is
    extended for xa binlog recovery.
2025-05-10 15:49:09 +03:00

47 lines
1.5 KiB
PHP

# ==== Purpose ====
#
# A lighter version of show_binlog_event.inc, with the same purpose
# to execute SHOW BINLOG EVENTS and mask non-deterministic output.
#
#
# Parameters:
#
# $binlog_file
# Filename for the 'IN' clause of SHOW BINLOG EVENTS. If none
# given, no argument is given to SHOW BINLOG EVENTS, meaning that
# it uses the first binlog. If you set this to "LAST", it prints
# the last binlog (according to SHOW MASTER STATUS).
#
# $binlog_start
# Position for the 'FROM' clause of SHOW BINLOG EVENTS. If none
# given, starts right after the Binlog_checkpoint_log_even.
#
# $regexp_replace
# A user's custom addon to standard preexisting list.
#
# $filter_cid
# boolean whether to filer out commit id (0) or not (1)
#
if ($binlog_start)
{
--let $_binlog_start=$binlog_start
}
if (!$binlog_start)
{
# consider instead ./binlog_start_pos.inc
--let $_binlog_start=256
}
if ($binlog_file)
{
--let $_in_binlog_file=in '$binlog_file'
}
--let $_from_binlog_start=from $_binlog_start
--replace_result "$_from_binlog_start" "from <binlog_start>" $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
--replace_column 2 # 5 #
--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ /file_id=[0-9]+/file_id=#/ /GTID [0-9]+-[0-9]+-[0-9]+/GTID #-#-#/ $replace_regexp
if ($filter_cid)
{
--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ /file_id=[0-9]+/file_id=#/ /GTID [0-9]+-[0-9]+-[0-9]+/GTID #-#-#/ / cid=[0-9]+// $replace_regexp
}
--eval show binlog events $_in_binlog_file from $_binlog_start