ITPub博客

首页 > 数据库 > MySQL > MySQL/InnoDB和Group Commit

MySQL/InnoDB和Group Commit

MySQL 作者:G8bao7 时间:2015-05-27 18:12:19 0 删除 编辑
from:
http://www.orczhou.com/index.php/2010/08/time-to-group-commit-1/
http://www.orczhou.com/index.php/2011/12/time-to-group-commit-2/
https://www.percona.com/blog/2011/07/13/testing-the-group-commit-fix/
http://insidemysql.sinaapp.com/article/94.html
http://blog.itpub.net/22664653/viewspace-1063134/

1. 什么是Group Commit

简单的,InnoDB在每次提交事务时,为了保证数据已经持久化到磁盘(Durable),需要调用一次fsync(或者是fdatasync、或者使用O_DIRECT选项等)来告知文件系统将可能在缓存中的数据刷新到磁盘(更多关于fsync)。而fsync操作本身是非常“昂贵”的(关于“昂贵”:消耗较多的IO资源,响应较慢):传统硬盘(10K转/分钟)大约每秒支撑150个fsync操作,SSD(Intel X25-M)大约每秒支撑1200个fsync操作。所以,如果每次事务提交都单独做fsync操作,那么这里将是系统TPS的一个瓶颈。所以就有了Group Commit的概念。

当多个事务并发时,我们让多个都在等待fsync的事务一起合并为仅调用一次fsync操作。这样的一个简单的优化将大大提高系统的吞吐量,Yoshinori Matsunobu的实验表明,这将带来五到六倍的性能提升。

MySQL/InnoDB在做事务的时候使用的日志先行(Write-ahead logging)的方式保证事务的快速和持久,所以每次事务完成都要求日志必须持久化到磁盘
    为了保证数据已经持久化到磁盘(Durable),需要调用一次fsync(或者是fdatasync、或者使用O_DIRECT选项等)来告知文件系统将可能在缓存中的数据刷新到磁盘(更多关于fsync)。而fsync操作本身是非常“昂贵”的(关于“昂贵”:消耗较多的IO资源,响应较慢):传统硬盘(10K转/分钟)大约每秒支撑150个fsync操作,SSD(Intel X25-M)大约每秒支撑1200个fsync操作。所以,如果每次事务提交都单独做fsync操作,那么这里将是系统TPS的一个瓶颈。
     
在Linux上对应的操作就是“write and fsync”,write速度是很快的,一般对应的写Page Cache,而fsync则要求文件系统把对应文件的哦Page Cache必须持久化到磁盘上,而对于传统磁盘一次写操作大约需要1~3ms(不说BBU),这意味着对于传统磁盘1秒钟最多最多做333~1000个事务,这是不理想的,对硬件的利用率(吞吐量)也是非常低。

所以,这里就有了Group操作的概念,即当好几个线程都要fsync同一个日志文件时,我们将这些fsync合并到一次来做。简单举例:我们让系统每2ms做一次fsync,这样如果这2ms内有100个线程都需要做fsync,那就赚到了,原本100个fsync都独立来做那耗时会非常多的。

2. MySQL/InnoDB与Group Commit

MySQL5.0开始,InnoDB就不再支持Group Commit了。在2005年,Peter Zaitsev就将此作为一个Bug提交,直到2009年在InnoDB Plugin1.0.4才将此问题修复。

2.1 为什么5.0之后MySQL/InnoDB无法支持Group Commit

究其更本原因发现,5.0之后MySQL开始支持“分布式事务和两阶段提交协议”(distributed transactions and Two Phase Commit /2PC),在代码实现时为了保证Binlog中的事务顺序和InnoDB Log(Transaction Log或者叫redo log)事务顺序一致,被动放弃了Group Commit。如果Binlog顺序不一致,那么备库就无法确保和主库有一致的数据。

InnoDB本身的代码实现是可以支持Group Commit的,我们来看下面的代码:

如果你设置了binlog_sync=1,则又多了一次fsync操作(参考MYSQL_BIN_LOG::flush_and_sync),这次操作在innobase_xa_prepare和innodb_commit之间:

binlog_prepare (do nothing)
innodb_prepare(innobase_xa_prepare)
...
binlog_commit
innobase_commit

innobase_xa_prepare()
write() and fsync() binary log
innobase_commit()

在innobase_xa_prepare函数中需要获取排他锁prepare_commit_mutex,直到上面的innodb_commit结束锁才释放,所以上面的binlog write and fsync也就无法Group操作了(当binlog_sync=1时)InnoDB就无法做Group_commit了,如果prepare_commit_mutex提前释放了,则可能导致InnoDB内部的事务顺序和Binlog内部事务的顺序不一致(原因参考: http://kristiannielsen.livejournal.com/[12254|12408|12553|12810].html)。

    当sync_binlog=1 和innodb-flush-log-at-trx-commit=1 同时启用时,在写密集的环境中性能的急剧下降


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/26250550/viewspace-1674192/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2013-11-04

  • 博文量
    496
  • 访问量
    1258293