IT袋

当前位置:主页 > 经验教程 > 建站编程 >

MySQL核心模块揭秘|二阶段提交prepare阶段

MySQL核心模块揭秘|二阶段提交prepare阶段

时间:2024-03-05 10:15:49 来源:IT袋 作者:马勇
导读:MySQL核心模块揭秘|二阶段提交prepare阶段,一篇关于MySQL核心模块揭秘|二阶段提交prepare阶段IT技巧方面的经验,接下来IT袋网带大家一起了解。 1. 二阶段提交 二阶段提交,顾名思义,包含两个阶段,它们是: pre

MySQL核心模块揭秘|二阶段提交prepare阶段

一篇关于MySQL核心模块揭秘|二阶段提交prepare阶段IT技巧方面的经验,接下来IT袋网带大家一起了解。

1. 二阶段提交

二阶段提交,顾名思义,包含两个阶段,它们是:

  • prepare 阶段。
  • commit 阶段。

我们只考虑 SQL 语句操作 InnoDB 表的场景,对于用户事务,是否使用二阶段提交,取决于是否开启了 binlog。

因为 MySQL 把 binlog 也看作一个存储引擎,开启 binlog,SQL 语句改变(插入、更新、删除)InnoDB 表的数据,这个 SQL 语句执行过程中,就涉及到两个存储引擎。

使用二阶段提交,就是为了保证两个存储引擎的数据一致性。

用户事务提交分为两种场景,如果开启了 binlog,它们都会使用二阶段提交。

场景 1:通过 BEGIN 或其它开始事务的语句,显式开始一个事务,用户手动执行 COMMIT 语句提交事务。

场景 2:没有显式开始的事务,一条 SQL 语句执行时,InnoDB 会隐式开始一个事务,SQL 语句执行完成之后,自动提交事务。

如果没有开启 binlog,SQL 语句改变表中数据,不产生 binlog,不用保证 binlog 和表中数据的一致性,用户事务也就不需要使用二阶段提交了。

InnoDB 内部事务是个特例,不管是否开启了 binlog,改变表中数据都不会产生 binlog 日志,所以内部事务不需要使用二阶段提交。

MySQL核心模块揭秘|二阶段提交prepare阶段

2. prepare 阶段

以下代码中,ha_prepare_low() 会调用 binlog 和 InnoDB 处理 prepare 逻辑的方法。

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

调用 ha_prepare_low() 之前,用户线程对象的durability_property属性值会被设置为HA_IGNORE_DURABILITY

这个属性和 redo 日志刷盘有关,InnoDB prepare 会用到。

2.1 binlog prepare

binlog 被看作一种存储引擎,它也有 prepare 阶段,代码如下:

// sql/binlog.cc
static int binlog_prepare(handlerton *, THD *thd, bool all) {
  DBUG_TRACE;
  if (!all) {
    thd->get_transaction()->store_commit_parent(
        mysql_bin_log.m_dependency_tracker.get_max_committed_timestamp());
  }
  return 0;
}

二阶段提交时,all = true,不会命中分支if (!all)。也就是说,在 prepare 阶段,binlog 什么也不会干。

2.2 InnoDB prepare

二阶段提交的 prepare 阶段,InnoDB 主要做五件事。

第 1 件,把分配给事务的所有 undo 段的状态从TRX_UNDO_ACTIVE修改为TRX_UNDO_PREPARED

进入二阶段提交的事务,都至少改变过(插入、更新、删除)一个用户表的一条记录,最少会分配 1 个 undo 段,最多会分配 4 个 undo 段。

相关阅读