【Mysql-InnoDB 系列】事务提交过程
系列文章:
一 背景知识
有了前面的一些知识,和 redo、undo、binlog,以及事务隔离级别的基本理解,下面我们整理事务提交的详细过程。
首先再明确一下几个 log 的作用:
1、redo
重做日志,用于实现事务的持久性,即 ACID 中的 D。结合本系列的第一篇文章,【Mysql-InnoDB 系列】InnoDB 架构包括内存架构和磁盘架构两部分。redo 日志在存储体现上也由两部分组成:
1-1 内存中的重做日志缓冲(redo log buffer),因为内存中是缓存,所以是易失的,server 挂掉或机器断点等原因导致宕机后丢失;
1-2 重做日志文件(redo log file),在磁盘上默认是两个文件存储。循环写入。
2、undo
redo 日志记录事务的行为,用于对页进行“重做”操作。但我们都知道事务还有 rollback 动作,回滚时需要 undo,利用其信息把数据回滚到修改之前。undo 是逻辑日志,只是将数据库逻辑地恢复到原来的样子,但数据结构和页本身在回滚之后可能大不相同。
另外,undo 还有一个作用,就是在 MVCC 中提供快照。这需要借助一个名为 history list 的结构,把 undo log 组织成一个链表:
3、binlog
二进制日志,用于进行 POINT-IN-TIME(PIT)恢复及主从复制(Replication)。与 redo log 区别:
(1)redo log 是 InnoDB 存储引擎层产生的,而 binlog 是 Mysql 数据库上层产生的;binlog 不仅仅针对 InnoDB 引擎,MySQL 数据库中的任何存储引擎对数据库的更改都会产生 binlog。
(2)内容形式。binlog 是一种逻辑日志,记录的是 SQL 语句。而 InnoDB 存储引擎层面的 redo log 是物理格式日志,记录的是对每个页的修改
(3)写入时间点:binlog 只在事务提交完成后进行一次写入,而 redo log 在事务进行中不断被写入,表现:日志并不是随事务提交的顺序进行写入的。如下图所示:
二 事务提交过程
1、开启二进制日志后的事务提交过程,两阶段提交::
(1)事务提交时 InnoDB 存储引擎进行 prepare 操作
(2)MySQL 数据库上层写入 binlog
(3)InnoDB 存储引擎层将日志写入 redo log 文件
a)修改内存中事务对应的信息,并将日志写入 redo log buffer
b)调用 fsync 将确保日志都从 redo log buffer 写入磁盘
一旦 MySQL 数据库上层写入 binlog 完成,就保证了事务的提交,即使之后数据库挂掉导致 redo log 未完成。此外还有一点必须注意,每个步骤都必须进行一次 fsync 才能保证上下层数据的一致。步骤(2)的 fsync 由 sync_binlog 控制,(3)的 fsync 由参数 innodb_flush_log_at_trx_commit 控制。
2、InnoDB 存储引擎事务提交顺序与上层的二进制日志
3、锁 prepare_commit_mutex 保证事务提交与 binlog 写入顺序:
三 总结
MySQL InnoDB 的事务模型、锁机制等设计,都是 InnoDB 架构设计的一部分。要全面了解它的设计实践,就必须从头看起。只有这样,才能够弄清楚它的设计思想,理解其实现上的精妙之处。
例如在上一篇文章中提到的问题,关于事务、redolog 写入的两个问题分析 ,看似简单,在网上也能搜到不少文章,但不深入了解,还是会有很多疑惑,甚至是理解错误。“重做日志”就是很典型的一个。 在整个系列中,redo log 指的是一种数据,但也可能是在说它的所在位置、存储形式【即 内存中的 redo log buffer, 以及磁盘上的:ib_logfile 文件】。如果不结合上下文和具体流程,那么就可能无法正确区分说的是哪一种情况。
不积跬步,无以至千里。立足脚下,基础扎实,才能走得更远。
版权声明: 本文为 InfoQ 作者【程序员架构进阶】的原创文章。
原文链接:【http://xie.infoq.cn/article/061d29f60d11bf0fd74919888】。文章转载请联系作者。
评论