MySQL 5.7 中的组提交(Group Commit) 是一种性能优化技术,主要目的是减少事务提交时频繁的磁盘IO开销,提高数据库的吞吐能力。
一、为什么需要组提交?
MySQL事务提交时需要确保数据持久化,这就涉及到以下日志的写入:
redo log(重做日志):用于崩溃恢复。
binlog:用于主从同步、数据恢复等。
undo log:用于事务回滚。
当事务频繁提交时,日志文件会频繁触发磁盘写入(fsync操作),这成为性能瓶颈。
为了降低这种开销,MySQL引入了组提交机制。
一、组提交的工作原理
组提交的核心思想是:将多个事务产生的日志合并到一起,批量一次性地写入磁盘,从而减少磁盘IO次数,提高事务提交的效率。
具体实现方式如下:
当多个事务同时进入提交阶段时,并不是每个事务立即单独地执行一次fsync磁盘刷盘操作。
MySQL会将多个事务短暂地积累成一个“组”,一次性地对该组中的所有事务日志进行磁盘刷盘,从而降低了单个事务的提交成本,提升吞吐量。
组提交相关参数:
binlog_group_commit_sync_delay
:含义:设置组提交刷盘延迟的等待时间。
默认值为
0
毫秒,表示无延迟。设置一个较小的延迟,可以等待更多事务一并提交,提高吞吐量。
binlog_group_commit_sync_no_delay_count
:表示累积达到多少个事务后,立即触发fsync刷盘。
以上两个参数是或的关系,满足任何一个条件时,就触发一次组提交。
组提交对两阶段提交(2PC)的影响
在MySQL中,事务的提交采用了“两阶段提交”(2PC)协议:
Prepare阶段:
事务的SQL语句已经执行完成,生成了redo log,但尚未写入binlog。
Commit阶段:
持久化binlog,并最终提交事务。
在引入组提交后,这个两阶段提交的流程稍有变化:
多个事务的Prepare阶段先完成(redolog写入内存或缓冲区),但不会立即刷盘。
等待短暂时间(由上述两个参数决定),积累多个事务后再进行一次性刷盘操作(fsync)。
此时,redolog和binlog一次性被刷盘完成,实现了批量的事务提交,大幅降低了磁盘的I/O成本。
关于write
和fsync
:
write
:将数据从内存写入文件系统的缓冲区,但不保证立即写入磁盘。fsync
:强制将文件系统缓冲区的数据立即持久化到磁盘,确保数据的持久性。
组提交就是优化了频繁执行fsync
的开销,通过批量执行fsync
操作,使得磁盘I/O效率大幅提高。