您的位置:首页 > 数据库 > MySQL

mysql半同步相关问题

2016-12-29 20:29 519 查看
半同步和MP相关.md


前言

最近有dba业务场景对数据质量要求比较高,而现在的主备切换可能会发生最后一个事务的数据质量问题,依赖半同步的超时时间来更大的保证数据质量。


半同步原理

半同步和非半同步最大的区别就是client 递交commit后是立马返回ack还是主备同步后再返回ack,如下图所示:

1.半同步时接受到1个备库的ack就会给客户端返回commit success,全同步就需要所有备库都返回ack才返回commit success



2.下图是半同步时主库需要操作的流程,大致分为解析sql、写binlog、commit事务、等待主备同步、返回commit success



注意:这里写了binlog主库立马就递交事务了,然后一直等待主备同步好的ack

上图中的半同步存在如下问题:

客户端事务在存储引擎层提交后,在得到从库确认的过程中,主库宕机了,此时,可能的情况有两种

1.事务还没发送到从库上

此时,客户端会收到事务提交失败的信息,客户端会重新提交该事务到新的主上,当宕机的主库重新启动后,以从库的身份重新加入到该主从结构中,会发现,该事务在从库中被提交了两次,一次是之前作为主的时候,一次是被新主同步过来的。

2.事务已经发送到从库上

此时,从库已经收到并应用了该事务,但是客户端仍然会收到事务提交失败的信息,重新提交该事务到新的主上。

在5.7中(集团alisql5.6也已有这个参数)引入了一种新的半同步方案:Loss-Less半同步复制。

引入了一个新的参数rpl_semi_sync_master_wait_point进行控制上图中“Waiting Slave dump”和“Storage Commit”的先后顺序。
AFTER_SYNC:Waiting Slave dump在Storage Commit之前,如下图所示:



AFTER_COMMIT:如下所示:



注:因为发生半同步降级的主要原因是主备同步不成功造成的,5.7中把等待同步放在storage commit(执行完此句后会递交事务,释放commit锁)之前可以很好的解掉上述两个问题中的数据重复问题。


关心的半同步时间点

下面是切换时候关注的几个点,5.6的数据库



1.在半同步模式下:

@startuml

== 事务开始 ==

client -> client: sql组成一个事务
client -> 主库: 事务commit  1.
主库 -> 主库:记binlog
主库 -> 备库:主备同步  2.
主库 -> 主库:commit事务
备库 -> 备库:同步数据
主库 -> 主库:等待同步
备库 -> 主库: 同步ack 3.
主库 -> client:commit success信号 4.

== 事务结束 ==

@enduml


以下都假设sync_binlog=1,rpl_semi_sync_master_wait_point=AFTER_COMMIT的时候
1.client递交了commit此时发生了主备切换,这时候主备数据是一致的,因为主备都没记binlog,此时切换后没有数据做回滚回补,也不会有数据质量问题,但是应用发生commit错误,在恢复后的新主库重新做此事务,无数据丢失情况
2.主备同步过程中发生了crash:主库记binlog了,备库没有记relaylog,此时老主恢复后会HA将老主库的数据回滚掉,在老备库中回补,无数据质量问题,但是应用发生ack错误,在恢复后的新主库上重新执行此事务,待老主恢复后进行回滚,在新主进行回补,此时新主就会产生数据重复(几率较大因为主备同步失败几率较大,受网络等影响)
3.都落盘备库返回ack时主备切换:主备都落盘了,不会进行回滚回补,无数据质量问题,但是ack失败,切换恢复后应用重新执行此事务,引发数据重复(几率较小,因为主要影响和耗时在主备同步阶段)
4.事务结束时发生切换,此时跟非回滚回补时候一样,不进行回滚回补,无数据质量问题

以下都假设sync_binlog=1,rpl_semi_sync_master_wait_point=AFTER_SYNC的时候
上面的2中,主库记binlog了,备库没同步成功,主库发生crash,此时主库未commit事务,机器重启后会恢复binlog中的事务,commit事务,HA回滚掉老主库这条事务,不回补,应用未ack成功重试,此时无数据重复问题,解决了上面2中的问题,前提是HA不回补
上面3中,主库记binlog,备库记relaylog后,但未commit事务成功就crash了,机器恢复后恢复binlog中未commit的事务,HA无需回滚回补,应用未ack成功重试,从而发生数据重复(几率较小,因为主要影响和耗时在主备同步阶段)

从上面两个推理可见:
AFTER_COMMIT和AFTER_SYNC都有可能发生数据重复的问题,但是使用AFTER_SYNC会大大减少数据重复问题

AFTER_COMMIT和AFTER_SYNC性能差别:
AFTER_COMMIT:记binlog后就commit事务,释放commit锁,但等待同步的过程中下一个事务可以进来了
AFTER_SYNC:要等待同步之后才commit事务,释放commit锁,这时下一个事务才能进来,性能会减低很多

2.在半同步发生降级后产生主备切换
跟非半同步模式下切换一样,可能发生数据质量问题


开启半同步时候的问题与解决

基于5.6的库,只靠半同步超时时间来保证主备的一致性
发生commit失败时候,不管发生切换还是未发生切换都可能会产生数据重复的问题,因为不能保证此时数据有没有落盘

半同步又发生主备切换时候,不管触发回滚回补还是无需进行回滚回补都有可能产生数据重复问题,但不会出现数据丢失问题

解决:

因为不管回滚回补都可能会出现数据重复的问题,所以考虑的只回滚不回补方案不可行

开启MP模式,发生降级时候开启MP模式,进入MP模式后引发切换,只回滚不回补,此方案对发生回滚回补触发的数据重复问题可解,但是对未触发回滚回补的情况还是不可解,且触发MP后引发切换,这样会导致应用不可用时间太长
应用进行改造,发生commit失败时重新commit前先检查一下上次commit是否落盘,问题可解,但是需要应用改造

半同步公认的问题(不开MP):
超时时间直接与数据库rt挂钩,设置不当严重影响性能,超时时间设置为业务能接受的 db 的最大 rt,必须保证 semi-sync 超时降级的场景下不影响应用可用性
超时发生降级变为异步可能产生数据质量问题


强保护MP


参考

MySQL半同步复制
MySQL 5.7 深度解析: 半同步复制技术
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: