为什么要组提交

因为MySQL为了保证redo log 和binlog的数据一致性,而采用了两阶段提交。即redo log 会先处理prepare状态,然后写binlog,当binlog写完之后,才去修改事务的最终状态为commit状态。

如果配置了双1,那么就会在prepare阶段,将redo log写入磁盘,而binlog也要刷盘,之后才可以提交事务,即一次事务要刷两次盘,影响性能。

并发事务的影响则更为明显,因为为了保证事务的顺序,需要加锁去保证,即一个事务完全写完之后,才能去写第二个。

因此,出现了组提交的优化。

组提交

以下的分析都是针对于双1配置。

在组提交中,prepare阶段不发生太多的变化,只是写完redo log 后,不再执行刷盘。

然后将commit阶段做了流水线处理,分为了三步,一共有3个队列,每个队列分别加锁:

  • 第一个队列,也就是flush stage:将存的一批事务,按其顺序将其redo log 刷盘,然后写binlog。但是这里的binlog只是写cache(缓存),不刷盘。
  • 第二个队列,sync stage:将队列中积攒的不同事务的binlog 刷盘。
  • 第三个队列,commit stage:将上述的队列按照顺序commit。

通过这样优化,就可以将之前的多个事务,每个事务需要两次I/O,且多个事务间一个执行完才能执行另一个,改为了多个事务一次I/O操作,且锁的粒度更低,事务间并发度更高。

注意的点

首先,在非组提交时,两阶段协议中,redo log处于prepare阶段时已经刷盘,但此时事务还没有commit。而binlog 需要刷完盘之后,才可以让事务提交。

提交的事务就无法回滚,因为可能会覆盖其他事务的提交。