通过sync_binlog=1控制事件持久化到磁盘,每次事务提交时进行fsync操作,将消耗大量的磁盘IOPS,如何最大化的提高性能,降低fsync对事务高并发的影响呢?
一. 二阶段提交
binlog是MySQL服务层产生的日志,每个线程有独立的缓存,在事务提交时才写入磁盘(fsync行为依赖sync_binlog设置),无法进行回滚,是逻辑的日志,记录行的改变或SQL语句。
redo日志(WAL)是InnoDB存储引擎产生的日志,在事务的执行过程中一直会产生,所有线程共享内存缓存(innodb_log_buffer_size),事务提交时会进行刷盘操作(fsync行为依赖innodb_flush_log_at_trx_commit设置),同时也会将没提交的事务日志顺带写入磁盘,写了redo的事务也能回滚。
binlog和redo是由不同的子系统产生的,两个子系统怎么协调,以保证binlog和redo的数据一致性呢?在分布式系统中,MySQL通过分布式事务(innodb_support_xa=1,8.0默认使用)来解决两者的一致性问题,在事务提交时,redo先写prepare 日志,并做刷盘,然后写binlog,并刷盘,写成功后,再进行写redo commit日志。
二阶段提交流程图:
当prepare日志写成功,在写binlog日志时MySQL宕机,binlog没写成功(a位置),恢复时将回滚该事务,因binlog没写成功,如果事务进行提交的话,将会造成redo和binlog的不一致,引起主从数据不一致。
当prepare日志和binlog都写成功,如果发生宕机(b位置),在恢复时会通过Xid去binlog日志查找是否有对应事务的完整日志,如binlog完整,尽管没有redo commit日志,也要进行事务提交,因binlog不能回滚,如果redo回滚,将会造成主从不一致,如没有完整的binlog日志将进行事务回滚。
二. binlog组提交
在MySQL 5.6之前,同时为了保障物理热备份工具,其备份数据的一致性,二阶段提交期间有prepare_commit_mutex锁,造成多个事务的提交是串行的,同时redo group commit也失效,引起性能问题。
为了解决该性能问题,5.6通过BLGC(Binary Log Group Commit)的机制进行了优化,将binlog的写分为三个阶段:flush,sync,commit,每个阶段由leader和follower组成,由leader控制follower的行为(follower不能成为leader),在commit阶段由leader按顺序调用存储引擎进行事务的提交,同时也去掉prepare_commit_mutex锁,提高了性能。
为了提高一次fsync操作更多的事务,提供了一些参数:
以上控制组提交的参数需要结合业务情况进行配置,当多线程(并发量)写时,效果更好。
如果文章对您有帮助,请友情帮转发+点赞哦!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。