innodb二阶段日志提交机制和组提交解析
2018-06-18 00:43:17来源:未知 阅读 ()
前些天在查看关于innodb_flush_log_at_trx_commit的官网解释时产生了一些疑问,关于
innodb_flush_log_at_trx_commit参数的详细解释参见官网:
https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit
InnoDB
log buffer are written to the log file after each transaction commit and the log file is flushed to disk approximately once per second.- 此值为0表示:redo log buffer的内容每秒会被写入文件系统缓存的redo log里,同时被flush(固化)到disk上的redo log file中。
- 此值为1表示:redo log buffer的内容会在事务commit时被写入文件系统缓存的redo log里,同时被flush(固化)到disk上的redo log file中。
- 此值为2表示:redo log buffer的内容会在事务commit时被写入文件系统缓存的redo log里,而文件系统缓存的redo log每秒一次被flush(固化)到disk上的redo log file中。
注意log buffer和undo buffer(也叫undo page)是在事务执行过程中就即时生成的(undo的disk文件位置默认在系统表空间中,5.6以后也可以自己指定独立的表空间),
- sync_binlog=0:表示fsync()的调用完全交给操作系统,即文件系统缓存中的binlog是否刷新到disk完全由操作系统控制。
- sync_binlog=1:表示在事务提交时,binlog一定会被固化到disk
- sync_binlog=N(N>1):数据库崩溃时,可能会丢失N-1个事务,具体原理也详见https://jin-yang.github.io/post/mysql-group-commit.html
假设有3个顺序执行的事务T1、T2、T3,Innodb层事务按照 T2、T3、T1 顺序提交,但Server层的binlog写入顺序为是T1、T2、T3(binlog不遵循WAL机制,只能猜测也是顺序写的),当 T2、T3在提交事务之后做了一个xtrabackup备份用于新建一个slave来做主从复制,那么搭建备库时由于T3事务已经完成,因此从T3之后开始同步,但是此时有可能丢失T1的binlog,造成主从不一致。
PS:个人感觉网站流传的T1、T2、T3组提交异常的那副图是错的,因此不建议引用。
结论:需要保证 binlog 的写入顺序和 InnoDB 事务提交顺序一致,用于 xtrabackup 备份恢复。
早期解决方案:
早期,使用 prepare_commit_mutex 保证顺序,只有当上一个事务 commit 后释放锁,下个事务才可以进行 prepare 操作,并且在每个事务过程中binlog 没有fsync() 的调用。
由于内存数据写入磁盘的开销很大,如果频繁 fsync() 把日志数据永久写入磁盘,数据库的性能将会急剧下降。为此提供 sync_binlog 参数来设置多少个 binlog 日志产生的时候调用一次 fsync() 把二进制日志刷入磁盘来提高整体性能,prepare_commit_mutex 的锁机制会严重影响高并发时的性能,而且 binlog 也无法执行组提交。
改进方案:
Mysql5.6 引入了组提交,并将提交过程分成 Flush stage、Sync stage、Commit stage 三个阶段。其实简单的说就是加入队列机制使得binlog写入顺序与事务执行顺序一致,加入队列的最大好处就是可以不获取prepare_commit_mutex锁也能实现不降低性能的日志顺序写。
Binlog组提交的基本思想是,引入队列机制保证Innodb commit顺序与binlog落盘顺序一致,并将事务分组,组内的binlog刷盘动作交给一个事务进行,实现组提交目的。在MySQL数据库上层进行提交时首先按顺序将其放入一个队列中,队列中的第一个事务称为leader,其他事务称为follow,leader控制着follow的行为。
- Flush Stage
1) 持有Lock_log mutex [leader持有,follower等待]。
2) 获取队列中的一组binlog(队列中的所有事务)。
3) 将binlog buffer到I/O cache。
4) 通知dump线程dump binlog。
- Sync Stage
1) 释放Lock_log mutex,持有Lock_sync mutex[leader持有,follower等待]。
2) 将一组binlog 落盘(sync动作,最耗时,假设sync_binlog为1)。
- Commit Stage
1) 释放Lock_sync mutex,持有Lock_commit mutex[leader持有,follower等待]。
2) 遍历队列中的事务,逐一进行innodb commit。
3) 释放Lock_commit mutex。
4) 唤醒队列中等待的线程。
说明:由于有多个队列,每个队列各自有mutex保护,队列之间是顺序的,约定进入队列的一个线程为leader,因此FLUSH阶段的leader可能是SYNC阶段的follower,但是follower永远是follower。当有一组事务在进行commit阶段时,其他新事物可以进行Flush阶段,从而使group commit不断生效。当然group commit的效果由队列中事务的数量决定,若每次队列中仅有一个事务,那么可能效果和之前差不多,甚至会更差。但当提交的事务越多时,group commit的效果越明显,数据库性能的提升也就越大。
与 binlog 组提交相关的参数主要包括了如下两个:
- binlog_max_flush_queue_time
单位为微秒,用于从 flush 队列中取事务的超时时间,这主要是防止并发事务过高,导致某些事务的 RT 上升,详细内容可以查看函数MYSQL_BIN_LOG::process_flush_stage_queue() 。
注意:该参数在 5.7 之后已经取消了。
- binlog_order_commits
当设置为 0 时,事务可能以和 binlog 不同的顺序提交,其性能会有稍微提升,但并不是特别明显.
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- mysql开启慢查询日志记录的方法 2019-09-23
- mysql日志信息查看与设置mysql-bin 2019-07-24
- 关于MySql 数据库InnoDB存储引擎介绍 2019-07-24
- 学会这 2 点,轻松看懂 MySQL 慢查询日志 2019-07-24
- 关于 MySQL 通用查询和慢查询日志,看这篇就够了! 2019-06-20
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash