改进方案:
Mysql5.6 引入了组提交,并将提交过程分成 Flush stage、Sync stage、Commit stage 三个阶段。其实简单的说就是加入队列机制使得binlog写入顺序与事务执行顺序一致,加入队列的最大好处就是可以不获取prepare_commit_mutex锁也能实现不降低性能的日志顺序写。
Binlog组提交的基本思想是,引入队列机制保证Innodb commit顺序与binlog落盘顺序一致,并将事务分组,组内的binlog刷盘动作交给一个事务进行,实现组提交目的。在MySQL数据库上层进行提交时首先按顺序将其放入一个队列中,队列中的第一个事务称为leader,其他事务称为follow,leader控制着follow的行为。
Flush Stage
1) 持有Lock_log mutex [leader持有,follower等待]。
2) 获取队列中的一组binlog(队列中的所有事务)。
3) 将binlog buffer到I/O cache。
4) 通知dump线程dump binlog。
Sync Stage
1) 释放Lock_log mutex,持有Lock_sync mutex[leader持有,follower等待]。
2) 将一组binlog 落盘(sync动作,最耗时,假设sync_binlog为1)。
Commit Stage
1) 释放Lock_sync mutex,持有Lock_commit mutex[leader持有,follower等待]。
2) 遍历队列中的事务,逐一进行innodb commit。
3) 释放Lock_commit mutex。
4) 唤醒队列中等待的线程。
说明:由于有多个队列,每个队列各自有mutex保护,队列之间是顺序的,约定进入队列的一个线程为leader,因此FLUSH阶段的leader可能是SYNC阶段的follower,但是follower永远是follower。当有一组事务在进行commit阶段时,其他新事物可以进行Flush阶段,从而使group commit不断生效。当然group commit的效果由队列中事务的数量决定,若每次队列中仅有一个事务,那么可能效果和之前差不多,甚至会更差。但当提交的事务越多时,group commit的效果越明显,数据库性能的提升也就越大。
与 binlog 组提交相关的参数主要包括了如下两个:
binlog_max_flush_queue_time
单位为微秒,用于从 flush 队列中取事务的超时时间,这主要是防止并发事务过高,导致某些事务的 RT 上升,详细内容可以查看函数MYSQL_BIN_LOG::process_flush_stage_queue() 。
注意:该参数在 5.7 之后已经取消了。
binlog_order_commits
当设置为 0 时,事务可能以和 binlog 不同的顺序提交,其性能会有稍微提升,但并不是特别明显.