阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

InnoDB二阶段日志提交机制

262次阅读
没有评论

共计 2406 个字符,预计需要花费 7 分钟才能阅读完成。

前些天在查看关于innodb_flush_log_at_trx_commit 的官网解释时产生了一些疑问,关于innodb_flush_log_at_trx_commit 参数的详细解释参见官网。

其中有一段是这么写的:
With a value of 2, the contents of the 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.
意思是:如果innodb_flush_log_at_trx_commit 的值设为 2,那么 log buffer 里的内容会在每次提交时被写入 log file,然后 logfile 也会被 flush 到 disk。
由于 innodb 的 log file 据我所知是在硬盘上的 ib_logfile,所以对于这里的 log file 被 flush 到 disk 很疑惑,难道 log buffer 和 disk 之间还存在了一层可以缓存 log file 的结构?
 
在查阅了大量中英文资料后,总算有了初步的了解,暂总结于此。
 
一、名词解释
在 innodb 存储引擎中,有一种独有的 log file,即 redo log file,因此对于 innodb 存储引擎来说,就存在两种 logfile:redo log 和 binlog.
redo log: 即 data 目录下的 ib_logfile0,ib_logfile1(个数由innodb_log_files_in_group 控制),innodb 存储引擎特有,在内存中有相应的 redo log buffer。
因此写 redo 时的 3 层结构为:redo log buffer—> 文件系统缓存中的 redo logfile—>disk 上的 redo log file
binlog: 默认在 data 目录下,也可以通过 log_bin 参数直接指定路径,文件名为默认为 <hostname>-bin 前缀的文件,在内存中没有 log buffer。
因此写 binlog 时的 2 层结构为:文件系统缓存中的 binlog—>disk 上的 binlog
 
二、二阶段日志写的流程
InnoDB 二阶段日志提交机制
当开启 binlog 后,如果会话发出了 commit 的请求,那么在 committed 之前,一系列的流程为:
1.prepare 阶段:
将 log buffer 的事务更改和事务 commit 信息写入文件系统缓存中的 redo log file,注意 log buffer 和 undo buffer(也叫 undo page)是在事务执行过程中就即时生成的(undo 默认在系统表空间中,5.6 以后也可以自己指定独立的表空间),文件系统缓存中的 redo log 是否 flush 到 disk,取决于innodb_flush_log_at_trx_commit 参数。
innodb_flush_log_at_trx_commit:
  • 此值为 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 中。
2. 写 binlog 阶段:
此阶段调用两个方法 write()和 fsync(),前者负责写文件系统缓存中的 binlog,后者负责将文件系统缓存中的 binlog 写入 disk 上的 bin log, 前者在此阶段一定会被调用,后者的调用机制由 sync_binlog 参数控制。
关于 sync_binlog 参数:
  • sync_binlog=0: 表示 fsync() 的调用完全交给操作系统,即文件系统缓存中的 binlog 是否刷新到 disk 完全由操作系统控制。
  • sync_binlog=1: 表示在事务提交时,binlog 一定会被固化到 disk
  • sync_binlog=N(N>1): 数据库崩溃时,可能会丢失 N - 1 个事务,具体原理也详见 http://www.linuxidc.com/Linux/2018-01/150187.htm
3. 最终 commit 阶段:
此阶段主要包含:server 告诉存储引擎,binlog 和 redo log 都已写好(至少在文件系统缓存级别已经写好),按正常机制提交数据吧,然后向会话返回 committed 的确认提交信息。
 
三、故障恢复解析
1. 如果在一阶段后崩溃,那么由于 binlog 未写,数据显然未能提交,算是失败的事务,无需前滚或回滚。(对于 Oracle 数据库则情况更为复杂,有些大事务即便未提交也可能有已经固化的数据,那么就需要进行回滚。还不清楚 mysql 的大事务是否也有未提交数据提前写入 disk 的机制)
2. 如果在二阶段后崩溃,那么只有一种情况可以保证数据完全不丢失,即:innodb_flush_log_at_trx_commit 和sync_binlog 都设置为 1,此时 redo log 和 binlog 都被固化到磁盘,可以保证 commit 后未写入的数据在 recovery 时被前滚提交。如果任意一个不为 1,那么都可能造成 binlog 和 redo log 不一致的情况,此时很可能丢失事务。
因此,为保证主从完全一致,主库的innodb_flush_log_at_trx_commit 和sync_binlog 都必须设置为 1。
 
至于 5.6 以后的为解决并发事务提交异常而出现的 3 阶段组提交机制,有待继续研究。
 
本文永久更新链接地址:http://www.linuxidc.com/Linux/2018-01/150186.htm
正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-22发表,共计2406字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中