前段时间看了下姜老师写的一个相关文章P8级面试难题,after_sync vs after_commit,哪个性能更好
写的特别详细,很有收获,这里结合一些之前看到的其他介绍,简单的汇总整理下.
首先了解下两个参数的区别
after_commit在主机事务提交后将日志传送到从机,after_sync是先传再提交。
image.png
上图文字说明可能大家感觉不是太直观具体,如果在源码层区分估计理解更加深些,参考[MySQL层事务提交流程简析](https://mp.weixin.qq.com/s/4Plg7Bc1KDuhKD5fqx6NSA
从图中可以看出在设置为after_sync时,则在第21步后确认,after_commit则在24步后确认.
可以看出after_commit如果在主库挂的时候,可能会导致数据丢失,而after_sync则不会丢失数据,但是可能在主库正要返回提交成功给客户端的时间点挂掉则会导致用户以为没有写入成功,但是从库已经存在数据的情况.
因此如果业务无法接受数据丢失的话推荐使用after_sync.
性能对比(来自姜老师分享文章)
一个事务在半同步模式下提交,无论是after_sync还是after_commit,都要经历4个阶段:
- InnoDB Redo File Write
- binlog File Flush & Sync
- InnoDB Redo File Commit(同时释放事务持有的锁)
- Send binlog to Slave
after_sync模式下,4个阶段的顺序为1->2->4->3,after_commit模式为1->2->3->4。这个顺序也解释了为什么after_commit为什么会有“幻读”问题。
现在假设阶段1、2、3各需要1ms时间,阶段4需要0.2ms时间,那么一次事务提交的时间:
T after_sync = 1 + 1 + 0.2 + 1 = 3.2 ms
T after_commit = 1 + 1 + 0.2 + 1 = 3.2 ms
以下分单线程,多线程对比下执行时间
单线程情况下
-
after_sync 提交流程
image.png -
after_commit 提交流程
image.png
可见单线程下after_commit性能较佳(如果主从不在相同机房,时间较长时,after_commit理论上会比after_sync单线程性能强很多)
多线程
在并发的场景下,若事务之间的修改不冲突,则事务是可以同时提交的,也就是可以进入到组提交(Group Commit)优化流程中。那么这时,事务的提交变为了:
image.png
事务TX1~TX4可以同时进入到提交阶段,这时会进入到MySQL的组提交优化中。这时产生的优化效果有:
-
InnoDB Redo Prepare只需要一次I/O操作
-
InnoDB binlog Write只需要一次I/O操作
-
接收到ACK后唤醒事务提交队列只需要一次
可以看到有组提交加持下数据库的的性能提升是非常明显的,假设没有组提交,并且唤醒等待线程需要0.02ms,则没有组提交的情况下,TX1~TX4事务所需要的时间为:
T[1~4 ]= ( 1 + 1 + 1 + 0.2 + 0.02 ) * 4 = 12.88 ms
在有组提交的优化加持下,TX1~TX4事务所需要的时间优化为了:
T[1~4] = 1 + 1 + 1 + 0.2 + 0.02 = 3.22 ms
网友评论