← Back to team overview

maria-developers team mailing list archive

Re: LP:1024058 - mysqld XA crash in replication slave


"Sergei Golubchik (JIRA)" <jira@xxxxxxxxxxxxxxxxxxxxx> writes:

>      [ https://mariadb.atlassian.net/browse/MDEV-633?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

[Taking this to maria-developers@, which is better for discussions like this]

> The problem here is very simple to explain. The server can use either
> mmap-based transaction coordinator for 2PC or a binary log. 2PC always uses
> binary log, if binary logging is enabled. But even if it is enabled
> globally, it is usually disabled in the replication slave thread unless
> --log-slave-updates is specified.
> One would probably get the same crash without replication, if one disables
> binary log manually with SET SQL_LOG_BIN=0;
> Possible fixes:
> * auto-enable binary log for 2PC transactions (bad, binlog will contain
> unwanted DDL and DML events).
> * abort 2PC transactions if binary log is locally disabled for this thread
> (worse, too easy to break the replication)
> * write Xid events to binlog even if binary log is locally disabled (best?)
> The last approach seems to be preferable. But in the future if we'll start
> recovering transactions from the binary log (doing only one sync per 2PC
> transaction), we'll have this problem again, because then we'll need the
> actual changes to be logged, not just the Xid.
> [~knielsen] - opinion?

First, I do not think SQL_LOG_BIN=0 or binlog enabled without
--log-slave-updates are common or very useful. And multi-engine transactions
are problematic in several ways. But we should not crash, of course. I would
find it acceptable to simply call each engine's commit method separately,
without 2PC, especially in stable 5.5 and below.

Note that we now have @@skip_replication, which can be used to log a
transaction to binlog without replicating it, similar to @@sql_log_bin but
maintaining 2PC and recovery.

If we really want, we could fix it 10.0 so that 2PC works even for binlog
disabled. As you say, probably writing the Xid to the binlog without any
associated DML events would be a reasonable way to do this. I would suggest
logging a separate new event to not confuse things with XID_LOG_EVENT, which
implies a commit of a prior transactions (there are facilities in 10.0 to
rewrite such event to a dummy event so we will not break old slaves).

With respect to a future recovering transactions from the binary log, it is
actually in any case very hard to recover a multi-engine transaction in this
way. The problem is when one engine is missing the transaction but the other
engine has it, and the event is logged with statement-based replication. But
we could simply not do this optimisation for multi-engine transactions, which
are really not very commonly used (for multi-engine transactions we would keep
the fsync() inside prepare()). Then things should work, for the normal case as
well as for binlog locally disabled.

So in summary, my immediate opinion would be:

 - In 5.5, commit each engine individually without 2PC when binlog is
   locally disabled.

 - In 10.0, optionally binlog just a new XID_RECOVERY_LOG_EVENT and use it in
   recovery if binlog is locally disabled.

Hope this helps,

 - Kristian.