MySQL 备库可以设置 sync_binlog 非 1 吗?
众所周知,防止断电丢失 Binlog、故障恢复过程丢失数据,MySQL 主库必须设置 sync_binlog=1
。那么作为备库可以例外吗?
作者:胡呈清,爱可生 DBA 团队成员,擅长故障分析、性能优化,个人博客:[简书 | 轻松的鱼],欢迎讨论。
爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
本文约 1200 字,预计阅读需要 4 分钟。
众所周知,防止断电丢失 Binlog、故障恢复过程丢失数据,MySQL 主库必须设置 sync_binlog=1
。那么作为备库可以例外吗?
我们的第一反应当然是不行,既然主库会丢数据,备库自然一样。但其实不然,**备库丢了数据是可以重新从主库上复制的,只要这个复制的位置和备库本身数据的位置一致就 OK 了,它们能一致吗?**本文将对这个问题进行讨论。
背景知识
为了更好的说明这个问题,下面赘述一下相关的知识点:
- InnoDB 的二阶段提交中,Prepare 阶段写 Redo Log,Commit 阶段写 Binlog,故障恢复时保证:
- 所有已提交事务的 Binlog 一定存在。
- 所有未提交事务一定不记录 Binlog。
- 备库设置
relay_log_info_repository = table
时,slave_relay_log_info
(即备库回放位置)的更新与 Relay Log 回放的 SQL 在同一个事务中提交。 - GTID 持久化在 Binlog 中,备库在某些条件下启动复制时会从 Executed_Gtid_Set 开始到主库复制数据。
根据以上 3 点,备库如果设置 sync_binlog
不为 1,在做故障恢复时的就会发生以下情况。
-
**事务状态:TRX_COMMITTED_IN_MEMORY、TRX_NOT_STARTED。**如果 Binlog 未落盘,事务会重做,数据将比 Binlog 多,
slave_relay_log_info
表记录的复制位置也将领先Executed_Gtid_Set
。 -
事务状态:TRX_PREPARED。 由于Binlog 未刷盘,Recovery 时会回滚事务,数据与 Binlog 是一致的,
slave_relay_log_info
表记录的复制位置等于 Executed_Gtid_Set。
如果备库断电恢复后,启动复制时用的位置由 slave_relay_log_info 决定
,则备库数据还是能正常复制数据,并且能与主库保持一致,只是 GTID 会出现跳号。
反之如果由 Executed_Gtid_Set 决定,则备库复制会因为重复回放事务而报错,需要进行修复。下面设计一个实验来进行验证。
实验过程
1. 设置备库参数并制造“故障”
备库参数设置如下,主库用工具并发写入数据(这里用的 mysqlslap),然后备库强制关机(reboot -f
)。
sync_binlog = 1000 innodb_flush_log_at_trx_commit = 1 relay_log_info_repository = table ##slave_relay_log_info 表为 innodb 表 relay_log_recovery = on gtid_mode = on
2. 重启备库
备库服务器开机后重启 MySQL,查看的信息如下。
show master status 输出的 Executed_Gtid_Set 如下: fb9b7d78-6eb5-11ec-985a-0242ac101704:1-167216 mysql> select * from slave_relay_log_info\G *************************** 1. row *************************** Number_of_lines: 7 Relay_log_name: ./localhost-relay-bin.000004 Relay_log_pos: 4 Master_log_name: mysql-bin.000001 Master_log_pos: 48159613 Sql_delay: 0 Number_of_workers: 0 Id: 1 Channel_name: 1 row in set (0.00 sec)
根据输出内容可知,从库的数据确实回放到了 mysql-bin.000001:48159613
,对应的 GTID 为:fb9b7d78-6eb5-11ec-985a-0242ac101704:167222
, 只是从库的 Binlog 有丢失,GTID 为:fb9b7d78-6eb5-11ec-985a-0242ac101704:1-167216
。
... SET @@SESSION.GTID_NEXT= 'fb9b7d78-6eb5-11ec-985a-0242ac101704:167222'/*!*/; ... ### INSERT INTO `mysqlslap`.`t` ### SET ### @1=167216 /* INT meta=0 nullable=0 is_null=0 */ # at 48159586 #220407 14:10:34 server id 123456 end_log_pos 48159613 Xid = 169239 COMMIT/*!*/; # at 48159613 ...
从库已经有 167222 事务对应的数据。
mysql> select * from t where id=167216; +--------+ | id | +--------+ | 167216 | +--------+ 1 row in set (0.00 sec)
3. 备库启动复制
Error Log 显示的起始位置和 slave_relay_log_info
内容一样,从主库的 mysql-bin.000001:48159613
开始,对应 GTID 为 167222+1。
>Slave I/O thread: Start asynchronous replication to master 'repl@10.186.61.32:3308' in log 'mysql-bin.000001' at position 48159613
但接下来 SQL 线程报错位置却是 mysql-bin.000001:48158146
,比开始位置还靠前,这个位置对应的 GTID 为 167217(即167216+1):
>2022-04-07T06:33:18.611181-00:00 4 [ERROR] Slave SQL for channel '': Could not execute Write_rows event on table mysqlslap.t; Duplicate entry '167212' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000001, end_log_pos 48158146, Error_code: 1062
而且解析从库 Relay Log(因为设置了 relay_log_recovery = on
,启动复制时会丢弃旧的未 Relay Log 重新到主库取 Binlog),第一个事务也是 SET @@SESSION.GTID_NEXT= 'fb9b7d78-6eb5-11ec-985a-0242ac101704:167217'/*!*/;
,而不是 167223。这说明了启动复制的位置并不是 slave_relay_log_info
记录的位置,而是从库的 GTID。
4. 重复以上测试
在启动从库复制前执行 change master to master_auto_position=0;
这回不报错,是从 167223 这个 GTID 开始复制数据,从库 GTID 会出现跳号。
mysql> show master status; +------------------+----------+--------------+------------------+-------------------------------------------------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------------------------------------------------+ | mysql-bin.000006 | 9976340 | | | fb9b7d78-6eb5-11ec-985a-0242ac101704:1-167216:167223-200670 | +------------------+----------+--------------+------------------+-------------------------------------------------------------+ 1 row in set (0.01 sec)
结论
从库 sync_binlog
设置不为 1,发生断电会丢失 Binlog,因为 GTID 持久化在 Binlog 中,因此也会丢失 GTID。但是数据和 slave_relay_log_info
表中保存的 SQL 线程回放位置一致。
此时:
- 如果
master_auto_position=0
,则从库重启复制时可以从正确的位置开始复制数据,从而与主库数据一致。不过从库会产生 GTID 跳号。 - 如果
master_auto_position=1
,则从库重启复制时会从 GTID 处开始复制数据,由于 GTID 有丢失,所以会重复回放事务,产生报错。
更多技术文章,请访问:https://opensource.actionsky.com/
关于 SQLE
SQLE 是一款全方位的 SQL 质量管理平台,覆盖开发至生产环境的 SQL 审核和管理。支持主流的开源、商业、国产数据库,为开发和运维提供流程自动化能力,提升上线效率,提高数据质量。
✨ Github:https://github.com/actiontech/sqle
📚 文档:https://actiontech.github.io/sqle-docs/
💻 官网:https://opensource.actionsky.com/sqle/
👥 微信群:请添加小助手加入 ActionOpenSource

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
前端又叠 buff 咯,拥有近 4 万 Star 的超级 HTML 增强工具:HTMX
在这个充满各种前端框架和工具的时代,开发者们往往会迷失在复杂的技术栈中。然而,有一款工具不仅简单易用,还能够大幅提升 HTML 开发的效率和灵活性。这就是 HTMX!这个开源项目在 GitHub 上已经收获了近 4 万个 Star,是不是很牛皮?那么,这款神器到底是什么,有哪些魔力呢? HTMX 是由 Big Sky Software 推出的一个强大的 HTML 增强工具,它的核心理念是将原本需要大量 JavaScript 实现的动态交互功能,通过扩展 HTML 的属性和标签轻松实现。你可以理解为 HTMX 是 HTML 的超级助力器,让普通的 HTML 网页焕发出新的生命力。 HTMX 如何改变开发者的世界? 简化交互逻辑 HTMX 允许你在 HTML 元素上直接声明需要的交互行为,比如点击、悬停、拖拽等,不需要编写复杂的 JavaScript 代码。例如,你只需在按钮上加上 hx-get 属性并指定请求的 URL,就可以实现点击按钮后动态加载数据的效果。再也不需要为这些简单的交互逻辑纠结写一大堆 JS 代码了! 动态加载与更新 还在为局部刷新和更新页面内容而苦恼吗?HTMX 为你带...
- 下一篇
记一次大库大表的治理过程
01 背景 理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将 部门中一核心应用,因为各种原因其依赖的MySQL数据库一直处于高水位运行,无论是硬件资源,还是磁盘使用率或者QPS等都处于较高水位,急需在大促前完成对应的治理,降低各项指标,以保障在大促期间平稳运行,以期更好的支撑前端业务。 02 基本情况 理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将 2.1 数据库 目前该数据库是一主两从,且都是零售的物理机,运行多年已都是过保机器。同时因为CPU和磁盘较大,已无同规格的物理机可以增加一个从库。同时其中一...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS关闭SELinux安全模块
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Windows10,CentOS7,CentOS8安装Nodejs环境
- CentOS8编译安装MySQL8.0.19
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- Red5直播服务器,属于Java语言的直播服务器
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS7,8上快速安装Gitea,搭建Git服务器