Databases 7 min read

Two‑Phase Commit: The Prepare Phase in MySQL 8.0 InnoDB and Binlog

This article explains how MySQL 8.0 implements the two‑phase commit protocol, detailing when it is used, the responsibilities of the prepare stage for both the binlog and InnoDB storage engines, and the five key actions InnoDB performs during preparation.

Aikesheng Open Source Community
Aikesheng Open Source Community
Aikesheng Open Source Community
Two‑Phase Commit: The Prepare Phase in MySQL 8.0 InnoDB and Binlog

The article examines MySQL 8.0.32’s two‑phase commit (2PC) mechanism, focusing on the prepare stage when the binary log (binlog) is enabled. It first outlines the two phases—prepare and commit—and explains that 2PC is required only when binlog is active because MySQL treats binlog as a storage engine, requiring coordination between binlog and InnoDB.

Two transaction scenarios are described: (1) an explicit transaction started with BEGIN and committed with COMMIT , and (2) an implicit transaction where a single DML statement starts and ends the transaction automatically. If binlog is disabled, 2PC is unnecessary, and internal InnoDB transactions never generate binlog entries.

2. Prepare Phase

During the prepare phase, the function MYSQL_BIN_LOG::prepare invokes ha_prepare_low() . Before this call, the thread’s durability_property is set to HA_IGNORE_DURABILITY , indicating that redo logs should not be flushed at this point.

2.1 Binlog Prepare

The binlog, treated as a storage engine, also has a prepare step, but when all is true (the 2PC case) the function simply returns without performing any action.

int MYSQL_BIN_LOG::prepare(THD *thd, bool all) {
  ...
  thd->durability_property = HA_IGNORE_DURABILITY;
  ...
  int error = ha_prepare_low(thd, all);
  ...
}

2.2 InnoDB Prepare

InnoDB’s prepare stage performs five main tasks:

Change the state of all undo segments assigned to the transaction from TRX_UNDO_ACTIVE to TRX_UNDO_PREPARED .

Write the transaction Xid into the header of each undo log group.

Update the in‑memory transaction object state from TRX_STATE_ACTIVE to TRX_STATE_PREPARED .

If the isolation level is READ‑UNCOMMITTED or READ‑COMMITTED, release shared and exclusive GAP locks held by the transaction.

Invoke trx_flush_logs() to handle redo‑log flushing logic (though actual flushing is deferred because durability_property is set to HA_IGNORE_DURABILITY ).

static void trx_flush_logs(trx_t *trx, lsn_t lsn) {
  ...
  switch (thd_requested_durability(trx->mysql_thd)) {
    case HA_IGNORE_DURABILITY:
      /* No immediate redo‑log flush during prepare */
      break;
    case HA_REGULAR_DURABILITY:
      trx_flush_log_if_needed(lsn, trx);
  }
}

Thus, the binlog prepare does nothing, while InnoDB prepare ensures undo segment states, transaction identifiers, lock release, and prepares redo‑log handling for later group commit.

3. Summary

When binlog is enabled, MySQL uses two‑phase commit to keep binlog and InnoDB data consistent. The binlog prepare step is a no‑op, whereas InnoDB’s prepare updates undo segment states to TRX_UNDO_PREPARED , records the Xid, changes the transaction state to TRX_STATE_PREPARED , releases certain locks, and sets up redo‑log flushing for the commit stage.

TransactionDatabaseInnoDBMySQLbinlogTwo-Phase Commit
Aikesheng Open Source Community
Written by

Aikesheng Open Source Community

The Aikesheng Open Source Community provides stable, enterprise‑grade MySQL open‑source tools and services, releases a premium open‑source component each year (1024), and continuously operates and maintains them.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.