深入理解半同步复制


先看下节点间的半同步复制时序图(注:半同步复制相关图示均源自王松磊@Ucloud)


5.7版本之后新增ack线程(单线程工作)用于接受应答,分摊dump线程的压力(老版本需要兼顾发送binlog和接受应答,这两个操作又是串行的)。


rpl_semi_sync_master_wait_point:AFTER_COMMIT;5.7版本开始默认为 AFTER_SYNC

两者区别在于,after_commit:binlog 传递到从库的relay log,同时主库提交事务但暂时不向客户端反馈 commit ok 的消息,直到收到ACK才反馈该消息。

after_sync:主库持续等待直到收到ACK之后,一并提交事务并向客户端反馈 commit ok 的消息。


下面为两者时序图,重点关注 Egine Commit 的时机





我们再次看下第一张半同步复制时序图,假设数据库并发量较大,势必会出现这样一种情况:worker线程需要往binlog写数据,而dump线程也需要读binlog并发送给从库的io线程。这就产生了一个并发的问题。解决并发的办法要么是事务要么就是锁了。5.7版本以前,利用的是互斥锁,将并发操作强行串行化。到了5.7版本,dump线程将不会产生互斥锁(worker线程是写操作,依然产生互斥锁)。示意图如下:






半同步复制退化为异步复制后,当重新收到从库的应答后可以重新恢复为半同步复制:

在事务提交时, 主库的worker线程会在半同步插件记录当前的binlog的文件名和位置点。从库IO线程在记录完relay log后, 会将relay log对应的主库的binlog的文件名和位置加到应答包中。 Dump线程在接受到应答后, 会对比slave发送的应答和半同步插件中记录的内容, 如果从库的复制已经追赶上主库,那么就恢复半同步复制。



参考资料:

5.7半同步复制新特性:https://sanwen8.cn/p/105GRDe.html


猜你喜欢

转载自blog.csdn.net/leonpenn/article/details/77001584