MySQL · 捉虫动态 · Relay log 中 GTID group 完整性检测

本文涉及的产品
RDS DuckDB + QuickBI 企业套餐,8核32GB + QuickBI 专业版
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDSClaw,2核4GB
简介: bug背景 官方 5.7.6 版本对 gtid 有非常多的改进和bugfix,其中有一个 bugfix 是针对 relay log 中没有接收完整的 gtid 事务的。正常的relay log 中的 gtid 事务应该是像下面这样: 1. gtid event 2. query event (

bug背景

官方 5.7.6 版本对 gtid 有非常多的改进和bugfix,其中有一个 bugfix 是针对 relay log 中没有接收完整的 gtid 事务的。正常的relay log 中的 gtid 事务应该是像下面这样:
1. gtid event
2. query event (begin)
3. row event (write/update/delete)
4. query event (commit)

上面这 4 个 event 序列构成一个 group。因为 IO 线程从主库接收 binlog 时,是以 event 为单位的,如果在 group 中间,比如3之后,stop slave 停掉IO线程的话,relay log 中就会记录一个不完整的事务。我们知道,GTID 的 auto_position 协议是通过计算主备库之间 GTID 集合的差集,然后来确定哪些 binlog 是要从主发给备的,备库用的集合就是 Retrieved_Gtid_Set 和 gtid_executed 的并集。IO 线程收到一个 gtid event 就会把它加入到 Retrieved_Gtid_Set 中,所以如果这个时候 start slave的话,最后这个不完整的事务是不会重新发送的,因为根据协议,主库认为备库已经有了这个事务,不需要再发送了。

修复分析

之所以会出现这种问题,是因为 IO 线程在处理的时候,没有将 gtid_event 和后面的事件序列当作一个整体来看待,只要收到开头的 gtid event,就认为整个 group 都已经收到。

所以官方的修复就是加一个事务边界检查器(Transaction_boundary_parser),只有当 IO 线程收到完整的 group,才将 gtid 加入到 Retrieved_Gtid_Set;同样在 mysqld 重启从 relay log 中初始化 Retrieved_Gtid_Set 时,也利用边界检查器判断 realy log 中的 gtid 事务是否完整。

下面就看下这个边界检查器是如何做判断的:

将 relay log 中的 event 序列分为2种,DDL 和 DML。

DDL 序列如下:
  DDL-1: GTID event
  DDL-2: User_var/Intvar/Rand event
  DDL-3: Query event

DML 序列如下:
  DML-1: GTID event
  DML-2: Query event(BEGIN)
  DML-3: Query event(除了 BEGIN/COMMIT/ROLLBACK) / Rows event / load event)
  DML-4: (Query event (COMMIT) | Query event(ROLLBACK) | Xid)

然后定义了5种状态,标识目前读到的 event 事件是在事务内还是事务外。
1. EVENT_PARSER_NONE // 在事务外,这个时候应该是读完 DDL-3 或者 DML-4
2. EVENT_PARSER_GTID // 读到了GTID event,处于事务中,这个时候应该是读到 DDL-1 或者 DDL-3
3. EVENT_PARSER_DDL // 处于事务中,读到 DDL-2
4. EVENT_PARSER_DML // 处于事务中,读到 DML-2 或者 DML-3
5. EVENT_PARSER_ERROR // 错误状态

边界检查器的实现是一个状态机,根据目前所处的状态和读到的event,确定下一步应该转移到什么状态。

比如对于下面这样的 event 序列:
1. gtid
2. begin
3. update rows
4. commit

状态是这样转移的,刚开始是 EVENT_PARSER_NONE,读到事件1,转为 EVENT_PARSER_GTID 状态,读到事件2,转为 EVENT_PARSER_DML 状态,读到事件3,转为EVENT_PARSER_DML状态,读到事件4,转为 EVENT_PARSER_NONE 状态。从EVENT_PARSER_NONE(事务外)最终又到 EVENT_PARSER_NONE,中间读了一个完整的事务。
详细的状态转移规则可以看官方patch

有了这个边界检测器后,IO 线程就能准确判断当前是处于事务外还是事务内,从而决定要不要把GTID添加到 Retrieved_Gtid_Set 中。

相关bug

对于 relay log 部分事务的问题,官方之前有个patch,其逻辑是对 relay log 中最后一个 gtid 做特殊处理。在 request dump 的时候,如果这个 gtid 不在备库的 gtid_executed 集合中的话,就把这个 gtid 从发送给主库的 gtid 集合里去掉,这样主库就会把这个最后的 gtid 事务重新发过来;如果这个 gtid 已经在备库的 gtid_executed 集合中的话,就不从发送给主库的 gtid 集合里去掉,这样主库库就不会重发。

但是这种修复方式依赖于 gtid_executed,并不是根据事务是否完整来决定要不要重拉事务,所以有的场景下会有问题,如 bug#72392 这种场景。

官方目前这种用边界检测的修复方式是比较好的,但是可能会有性能上的问题,因为每个的 event 都要用边界检查器判断下,像 query event 需要要进行字符串比较。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
存储 SQL 关系型数据库
MySQL日志详解——日志分类、二进制日志bin log、回滚日志undo log、重做日志redo log
MySQL日志详解——日志分类、二进制日志bin log、回滚日志undo log、重做日志redo log、原理、写入过程;binlog与redolog区别、update语句的执行流程、两阶段提交、主从复制、三种日志的使用场景;查询日志、慢查询日志、错误日志等其他几类日志
1120 35
MySQL日志详解——日志分类、二进制日志bin log、回滚日志undo log、重做日志redo log
|
存储 缓存 关系型数据库
图解MySQL【日志】——Redo Log
Redo Log(重做日志)是数据库中用于记录数据页修改的物理日志,确保事务的持久性和一致性。其主要作用包括崩溃恢复、提高性能和保证事务一致性。Redo Log 通过先写日志的方式,在内存中缓存修改操作,并在适当时候刷入磁盘,减少随机写入带来的性能损耗。WAL(Write-Ahead Logging)技术的核心思想是先将修改操作记录到日志文件中,再择机写入磁盘,从而实现高效且安全的数据持久化。Redo Log 的持久化过程涉及 Redo Log Buffer 和不同刷盘时机的控制参数(如 `innodb_flush_log_at_trx_commit`),以平衡性能与数据安全性。
825 5
图解MySQL【日志】——Redo Log
|
存储 SQL 关系型数据库
mysql的undo log、redo log、bin log、buffer pool
MySQL的undo log、redo log、bin log和buffer pool是确保数据库高效、安全和可靠运行的关键组件。理解这些组件的工作原理和作用,对于优化数据库性能和保障数据安全具有重要意义。通过适当的配置和优化,可以显著提升MySQL的运行效率和数据可靠性。
323 16
|
存储 SQL 关系型数据库
mysql的undo log、redo log、bin log、buffer pool
MySQL的undo log、redo log、bin log和buffer pool是确保数据库高效、安全和可靠运行的关键组件。理解这些组件的工作原理和作用,对于优化数据库性能和保障数据安全具有重要意义。通过适当的配置和优化,可以显著提升MySQL的运行效率和数据可靠性。
234 4
|
SQL 关系型数据库 MySQL
MySQL事务日志-Undo Log工作原理分析
事务的持久性是交由Redo Log来保证,原子性则是交由Undo Log来保证。如果事务中的SQL执行到一半出现错误,需要把前面已经执行过的SQL撤销以达到原子性的目的,这个过程也叫做"回滚",所以Undo Log也叫回滚日志。
836 7
MySQL事务日志-Undo Log工作原理分析
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
2532 14
MySQL事务日志-Redo Log工作原理分析
|
SQL 存储 关系型数据库
简单聊聊MySQL的三大日志(Redo Log、Binlog和Undo Log)各有什么区别
在MySQL数据库管理中,理解Redo Log(重做日志)、Binlog(二进制日志)和Undo Log(回滚日志)至关重要。Redo Log确保数据持久性和崩溃恢复;Binlog用于主从复制和数据恢复,记录逻辑操作;Undo Log支持事务的原子性和隔离性,实现回滚与MVCC。三者协同工作,保障事务ACID特性。文章还详细解析了日志写入流程及可能的异常情况,帮助深入理解数据库日志机制。
1666 0
|
存储 关系型数据库 MySQL
图解MySQL【日志】——Undo Log
Undo Log(回滚日志)是 MySQL 中用于实现事务原子性和一致性的关键机制。在默认的自动提交模式下,MySQL 隐式开启事务,每条增删改语句都会记录到 Undo Log 中。其主要作用包括:
657 0
|
API C# 开发框架
WPF与Web服务集成大揭秘:手把手教你调用RESTful API,客户端与服务器端优劣对比全解析!
【8月更文挑战第31天】在现代软件开发中,WPF 和 Web 服务各具特色。WPF 以其出色的界面展示能力受到欢迎,而 Web 服务则凭借跨平台和易维护性在互联网应用中占有一席之地。本文探讨了 WPF 如何通过 HttpClient 类调用 RESTful API,并展示了基于 ASP.NET Core 的 Web 服务如何实现同样的功能。通过对比分析,揭示了两者各自的优缺点:WPF 客户端直接处理数据,减轻服务器负担,但需处理网络异常;Web 服务则能利用服务器端功能如缓存和权限验证,但可能增加服务器负载。希望本文能帮助开发者根据具体需求选择合适的技术方案。
1222 1
|
存储 关系型数据库 MySQL
MySQL中的Redo Log、Undo Log和Binlog:深入解析
【10月更文挑战第21天】在数据库管理系统中,日志是保障数据一致性和完整性的关键机制。MySQL作为一种广泛使用的关系型数据库管理系统,提供了多种日志类型来满足不同的需求。本文将详细介绍MySQL中的Redo Log、Undo Log和Binlog,从背景、业务场景、功能、底层实现原理、使用措施等方面进行详细分析,并通过Java代码示例展示如何与这些日志进行交互。
1233 0

相关产品

  • 云数据库 RDS MySQL 版
  • 推荐镜像

    更多
    下一篇
    开通oss服务