MySQL的XID

XID是什么

MySQL Binlog 文件由 event 组成,event 有不同的类型,而XID_EVENT 表示一个事务的提交操作。

当事务提交时,在 binlog 依赖的内部 XA 中,额外添加了 Xid 结构,binlog 有多种数据类型:

  1. statement 格式,记录为基本语句,包含 Commit
  2. row 格式,记录为基于行
  3. mixed 格式,日志记录使用混合格式

不论是 statement 还是 row 格式,binlog 都会添加一个 XID_EVENT 作为事务的结束,该事件记录了事务的 ID 也就是 Xid,在 MySQL 进行崩溃恢复时根据 binlog 中提交的情况来决定如何恢复。

XID如何生成

MySQL 内部维护了一个全局变量 global_query_id,每次执行语句的时候将它赋值给 Query_id,然后给这个变量加 1。如果当前语句是这个事务执行的第一条语句,那么 MySQL 还会同时把 Query_id 赋值给这个事务的 Xid。

XID是唯一的吗

而 global_query_id 是一个纯内存变量,重启之后就清零了。所以你就知道了,在同一个数据库实例中,不同事务的 Xid 也是有可能相同的。

但是 MySQL 重启之后会重新生成新的 binlog 文件,这就保证了,同一个 binlog 文件里,Xid 一定是惟一的。

虽然 MySQL 重启不会导致同一个 binlog 里面出现两个相同的 Xid,但是如果 global_query_id 达到上限后,就会继续从 0 开始计数。从理论上讲,还是就会出现同一个 binlog 里面出现相同 Xid 的场景。

因为 global_query_id 定义的长度是 8 个字节,这个自增值的上限是 2^64-1。要出现这种情况,必须是下面这样的过程:

执行一个事务,假设 Xid 是 A;

接下来执行 2^64次查询语句,让 global_query_id 回到 A;

再启动一个事务,这个事务的 Xid 也是 A。

不过,2^64这个值太大了,大到你可以认为这个可能性只会存在于理论上。

XID的作用

二阶段提交

步骤如下

  • InnoDB 进入 Prepare 阶段,并且 write/sync redo log,写 redo log,将事务的 xid 写入到 redo 日志中,binlog 不作任何操作

  • 进行 write/sync binlog,写 binlog 日志,也会把 xid 写入到 binlog

  • 调用 InnoDB 引擎的 commit 完成事务的提交,将 commit 信息写入到 redo 日志中

MySQL崩溃恢复会有什么操作

如果 redo log 里面的事务是完整的,也就是已经有了 commit 标识,则直接提交;

如果 redo log 里面的事务只有完整的 prepare,则判断对应的事务 binlog 是否存在并完整:

a. 如果是,则提交事务;

b. 否则,回滚事务。

MySQL 怎么知道 binlog 是完整的

一个事务的 binlog 是有完整格式的:statement 格式的 binlog,最后会有 COMMIT;

row 格式的 binlog,最后会有一个 XID event。

崩溃恢复的时候,会按顺序扫描 redo log:

如果碰到既有 prepare、又有 commit 的 redo log,就直接提交;

如果碰到只有 parepare、而没有 commit 的 redo log,就拿着 XID 去 binlog 找对应的事务。

MySQL解释如下

扫描最后一个binlog获取XID生成一个hash table,再扫描redo将checkpoint之后所有XID,如果XID在hash table里面则提交,不在则回滚。

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值