innodb的group commit的小结

浏览了group commit的几篇文章,尤其是一个老外的4篇blog,对innodb的group commit的前因后果有了一个较清晰的了解。
起因:
硬盘IO次数是有限的,是数据库性能的瓶颈。数据库为了持久性,必须把事务所做的修改flush到硬盘上,最后需要调用fsync()来完成一个IO,所以速度很慢。这样,在并发环境下,事务都会排队等在最后一步。于是为了节省硬盘IO,可以把几次IO合并成一个IO去做,只用一次fsync()就可以完成,这样就节省了开销。然而mysql是两层架构,innodb有自己的日志系统,这一步可以group commit。而mysql本身有一个binlog,这个binlog是mysql层的日志,可以用来进行主从同步等。由于mysql上层并没有事务的概念,为了保证mysql层的binlog和innodb的修改是一致的,需要进行一个同步。
 
做法:
如果启用binary log,那么mysql就会用XA的两阶段提交协议来保证binary log和存储引擎的数据一致性,于是一个commit就会变成三步。
原来的commit:
innobase_commit()
{
===fast===
trx->flush_log_later=TRUE;
innobase_commit_low(trx);
trx->flush_log_later=FALSE;
===slow===
trx_commit_complete_for_mysql(trx);
}
如果用了binlog:
+innobase_xa_prepare()
+write() and fsync()binary log
innobase_commit()
在innobase_xa_prepare(),Innodb会lock prepare_commit_mutex,然后直到innobase_commit()的快速部分结束后,这个mutex才会被释放。这边就会成为一个瓶颈。使得当一个事务执行完innobase_commit()的快速部分前,其他的事务都会等在第一步innobase_xa_prepare()那边,因此别的事务没法进入trx_commit_complete_for_mysql(trx)去共享那个fsync操作,group commit也就失去了意义。
 
解决方法:
facebook的方法:
引入ticket的概念,在innobase_xa_prepare()阶段让每个事务领一个只增的ticket作为提交的顺序,只要顺序确定了,那么就不必担心乱序的问题,可以group commit了。
博主的方法:
直接用binlog的LSN作为commit的order。这样连ticket的锁也省了。
 
心得:
以前曾经做过一个小内存数据库,当时不要求日志(演示用小项目),不过在研发中也讨论过日志的实现。当时有一个需求要数个端之间的同步,对于多事务情况下的利用日志恢复也做过思考。之前一个简单的做法是记sql语句,显然在并发环境下这样是没法做了。当时也想过很多做法,很麻烦,时间原因也仅仅有了想法,没去实现。(感觉技术上的东西,没实际做只是想想对于大多数人来说和没有思考差不多)看了innodb的group commit的改进,和我们当时的这个需求有点像,因此就花了点时间跟踪了一下。
看了代码修改,也看了博客分析,大牛就是大牛,问题说得很清楚,解决的方法也很简单。
PS:这个分析是上周看的,因为琐事耽搁,本周才做了整理,感觉有点乱,等过几天再分析一下。以前对mysql这种storage engine与上层分离的架构只是浅浅的了解,在group commit这个问题上,暴露了这种架构的潜在问题,直觉上认为这个作为一个切入点了解mysql与innodb的交互是不错的角度,会再度跟进。
再PS:记忆力真的下降了,不记记笔记不行啊
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值