MySQL在开启Binary Log的情况下,使用2PC(图1)来保证事务(XA)完整性的,每次提交事务需要做: ~~~ 1) prepare phase: 记录prepare信息到引擎层的Redo Log,fsync到磁盘 2) commit phase: A) 记录commit信息到MySQL Server层的Binary Log,fsync到磁盘 B) 记录commit信息到引擎层的Redo Log,fsync到磁盘 ~~~ 每个事务在提交的时候都要做3次fsync以确保日志真正的落盘,这样在log里,一个事务就会有3种状态: ~~~ 状态1: Redo Log里存在,Binary Log里也存在 --正常情况,crash恢复时需要commit 状态2: Redo Log里存在,Binary Log里不存在 --prepare完毕后发生crash,恢复时需要rollback 状态3: Redo Log里不存在,Binary Log里也不存在 --提交失败,无需处理 ~~~ [![2pc.png](https://oss.showapi.com/doc/2096/240/5e1cee5c-63a7-4b14-946d-114dae35e430.png)](http://mysql.taobao.org/index.php?title=%E6%96%87%E4%BB%B6:2pc.png) 这样,无论处于任何一个状态,事务的完整性都不会被破坏,但是每次提交会产生3次fsync,性能非常低。  为了提升性能,MySQL 5.6增加了group commit功能,当多个事务并发提交时,让多个都在等待fsync的事务合并做一次fsync,大大提升了吞吐量。  但是这个优化还需要引擎层的配合,引擎层需要"一切行动听指挥",不要"任性"的做fsync,需要对当前THD做HA_IGNORE_DURABILITY判断,代码如下: ~~~ static bool tokudb_fsync_on_commit(THD *thd) { #if MYSQL_VERSION_ID >= 50600 if (thd_get_durability_property(thd) == HA_IGNORE_DURABILITY) return false; else #endif return THDVAR(thd, commit_sync) != 0; } ~~~ TokuDB 7.5.4版本即将包含这个特性,官方透露,600 tokudb commits/sec只产生120个tokudb fsyncs。