前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL#复制 - crash-safe Replication - 上

MySQL#复制 - crash-safe Replication - 上

作者头像
用户1278550
发布2020-11-02 14:23:34
7250
发布2020-11-02 14:23:34
举报
文章被收录于专栏:idbaidba

本篇文章要讨论的是复制环境下的crash-safe,换句话说的意思就是:保证无论在master还是slave发生异常crash拉起后,整个复制结构是支持ACID特性的,也意味着仅考虑支持事务的存储引擎(MyISAM场景不考虑)。本篇为上篇,内容为5.5/5.6,不包括MTS场景。5.7+ MTS场景见下篇。


主库配置

在讨论从库之前,首先,主库的不合理设置同样会在一些情况下造成从库发生复制故障,所以主库得需要是双1的。 非双1有很可能造成从库比主库多事务,所以从库异常是比较容易发生的事情。

复制中一致性保证影响因素

一句话简化看这个问题,就是保证复制过程中的两个线程:IO Thread、SQL Thread不掉链子。

IO Thread,用于接收主库binlog events,写入relay log。 SQL Thread,用于应用relay log到数据文件中。

对于从库节点,如果发生db crash或者宕机,IO Thread要知道从哪里继续拉取binlog,同时SQL Thread要知道从relay log中的哪个位置点开始继续应用日志。即恢复之前的复制进度,不能漏应用事务,也不能重复应用事务。(类似断点续传)

所以需要有一个地方能够存储更新进度:————

MySQL 5.5

5.5是远古版本,当时:

IO Thread和SQL Thread分别往master.inforelay-log.info两个文件中更新元数据。对应的元数据信息被称作“master info”与“relay log info”。

但默认情况下,这俩文件更新频次是非常低的。

关于写master info和relay log info,有两个相关参数可以“尽量”保证。

sync_master_info,指每经过sync_master_info个events,slave将master.info文件落盘。为0时则仅靠OS来控制。

sync_relay_log_info,指每经过sync_relay_log_info个events,slave将relay-log.info文件落盘。为0时则仅靠OS来控制。

默认值为10000,很夸张。 如果将两个info参数设置为1,可保证每次接收或应用events之后,再将文件写入磁盘。

听起来很靠谱,但是这样搞会有两个问题: 1、性能差。 2、提交事务在先,更新复制信息到文件在后,极端情况下仍然可能出错。

上述更新过程如下: 1、apply relay log中的事务 2、再更新relay-log.info文件

复制相关的元数据信息出现问题会产生什么后果?举一个简单的故障例子: 如果异常crash后拉起,SQL Thread若读到了旧的位置(relay-log.info没及时更新),这样会重新apply某个提交过的事务,“恶名昭著”的1032、1062就来了。如果没有主键或唯一键的事务可能会更糟——没办法简单通过SHOW SLAVE STATUS去检查主从数据是否不一致了。这个场景好理解。

至于写relay log这个操作本身,也是难以保证极端情况下crash是没问题的,即便是将sync_relay_log设置为1也如此。

总结如下,因为

  • master.info的位置
  • relay-log.info的位置
  • relay log里的内容

三者均不100%可信(即便相关参数都设置成1) 所以,MySQL 5.5在复制环境中是不安全的。

MySQL 5.6

有个重大改进,将master info和relay log info写入了表里,也就是对应mysql.slave_master_infomysql.slave_relay_log_info这俩张表,该表早期还是MyISAM,需要在5.6安装好后手动改为InnoDB。当然在某个5.6的小版本之后就默认为InnoDB了。

该特性对应了两个参数:

master_info_repository = TABLE | FILE
relay_log_info_repository = TABLE | FILE 

而InnoDB就很舒服了,意味着IO Thread和SQL Thread更新对应的元数据信息时,是支持事务的,妙啊。

支持事务更新relay log info的过程就是:

START TRANSACTION;
apply log event;
UPDATE mysql.slave_relay_log_info
SET Master_log_pos = Exec_Master_Log_Pos,
Master_log_name = Relay_Master_Log_File,
Relay_log_name = Relay_Log_File,
Relay_log_pos = Relay_Log_Pos;
COMMIT;

简单想一下就可以发现,其实只需要保证relay log info不出错就行了,故只需要配置如下即可保证crash safe:

relay_log_info_repository = TABLE
relay_log_recovery = ON

补充,打开relay_log_recovery时,在重启后会发生什么呢?

  • IO Thread的位点会重新设置为SQL Thread的位点(以relay log info为准)
  • 以SQL Thread的位置创建一个新的relay log

通过上述两个参数的设置,则可以保证SQL Thread每一次apply事务的时候,能及时更新自己的relay log info的信息,就足够了。在从库异常crash拉起后,只需要以relay log info覆盖到master info,然后让IO Thread重新拉取relay log即可。

so,master_info_repository存文件还是存表里,其实没所谓,不过设置为TABLE也是不错的选择,理由是强迫症或者为了统一称它们为“双TABLE”听起来很舒服。

MySQL 5.6 + GTID

走的协议不一样了,用的COM_BINLOG_DUMP_GTID,所以定位方式也不一样了。

  • gtid_mode = ON & MASTER_AUTO_POSITION = 0: 虽然真有DBA这样配,但手册里也没怎么提及这种配置,非主流不讨论。
  • gtid_mode = ON & MASTER_AUTO_POSITION = 1: 和file & pos的方式一致。

另外还有一种配置如下:

log_slave_updates(5.6开gtid必须打开此参数)
log_bin(5.6开gtid必须打开此参数)
relay_log_recovery = ON
sync_binlog = 1

如果按上述配置,relay_log_info_repository是FILE或者TABLE也就无所谓了,因为auto-position不依赖relay log info了,而是通过Executed_gtid_set去判断自己和主库的差异事务。 细节可以阅读响应代码:

Rpl_slave.cc:request_dump()
Rpl_master.cc:com_binlog_dump_gtid()

sync_binlog=1是必备的,需要binlog安全落地。因为GTID信息依赖binlog,从库可以通过自己的binlog获取自身完整的Executed_gtid_set。

总之,如果非双1时,可能会有问题,有兴趣可瞟一眼Yoshinori大佬report的 https://bugs.mysql.com/bug.php?id=70659

当然,上述所有的场景innodb_flush_log_at_trx_commit也记得设置为1。 简言之: MASTER_AUTO_POSITION=1场景要依赖GTID信息,GTID信息依赖binlog。

安全配置建议

MySQL 5.5:

怎么配置都没有囊括100%的crash场景,极端情况下仍然会crash unsafe。

如果愿意牺牲性能,保证较高的安全性可以这样设置。

sync_relay_log_info = 1
relay_log_recovery = ON
MySQL 5.6:
  • 单线程复制限定。
  • 存储引擎限定:仅支持InnoDB,(TokuDB、RocksDB也应该可)。
  • 主库:双1
  • 从库(开不开MASTER_AUTO_POSITION通用):
relay_log_info_repository = TABLE
relay_log_recovery = ON
-- 即便是从库同样也请双1:
sync_binlog = 1
innodb_flush_log_at_trx_commit = 1

如果5.6开启了MTS,先不讨论,官方MySQL 5.6 MTS那时还算个玩具。 下篇见,直接讨论MySQL 5.7 MTS,那样的场景下将复杂一点点。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-10-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 yangyidba 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 主库配置
  • 复制中一致性保证影响因素
  • MySQL 5.5
  • MySQL 5.6
  • MySQL 5.6 + GTID
  • 安全配置建议
    • MySQL 5.5:
      • MySQL 5.6:
      相关产品与服务
      云数据库 SQL Server
      腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档