事务的实现-redo log和undo log来完成

事务

InnoDB中的事务完全符合ACID特性:

  • 原子性(atomicity)
  • 一致性(consistency)
  • 隔离性(isolation)
  • 持久性(durability)

通过在事务中使用SAVE WORK函数可以建立保存点。保存点可以通过ROLLBACK WORK: n来回滚。

事务的实现

事务的隔离性由上一章讲的锁来实现。原子性、一致性、持久性通过数据库的redo log和undo log来完成。redo log称为重做日志,用来保证事务的原子性和持久性;undo log用来保证事务的一致性。

redo log和undo log不是相互的逆过程,redo log是物理日志,而undo log是操作的逆向操作,是逻辑日志。

redo

redo log是用来实现事务的持久性,即ACID中的D,由内存中的redo log buffer和磁盘的redo log file组成。

当事务提交时,必须将所有日志写入重做日志文件进行持久化,待事务的COMMIT操作完成才算完成。重做日志指的是redo log和undo log,redo log是用来保证事务的吃就行,undo log用来帮助事务回滚及MVCC的功能。redo log基本顺序写,而undo log是需要进行随机读写的。

在每次将重做日志缓冲写入重做日志文件后,InnoDB都调用一次fsync操作,确保日志写入重做日志文件。磁盘性能决定了事务提交的性能。

在数据库中还有一种二进制日志(binlog),用来进行POINT-IN-TIME的恢复和主从复制环境的建立。redo log是在InnoDB存储引擎层产生,bin log是在MySQL数据库的上层产生,并且不只是对InnoDB引擎的;同时bin log是逻辑日志,记录的是对应的SQL语句,redo log是物理格式的日志,记录的是每个页的修改;binlog只在事务提交完成后一次写入,redo log在事务进行中不断地被写入,因此redo log不是随事务提交的顺序进行写入的。

redo log是物理日志,因此它是幂等的,而bin log由于是逻辑日志,如INSERT等操作不是幂等的,所以它不能被重复执行。

undo

在对数据库进行修改时,InnoDB存储引擎不但会产生redo,还会产生一定量的undo。这样如果用户执行的事务或语句由于某种原因失败了,又或者用户用一条ROLLBACK语句请求回滚,就可以利用这些undo信息将数据回滚到修改之前的样子。

与redo log放在文件不同,undo放在数据库内部的一个特殊段中,称为undo段,位于共享表空间中。

undo是逻辑日志,回滚时修改会被逻辑地取消,数据结构和页本身在回滚之后可能不太相同,因为这个过程中可能有其他并发的事务,因此不能将一个页回滚到事务开始的样子。InnoDB回滚时实际上是做与之前相反的工作,例如对于INSERT会回滚一个DELETE操作。

undo除了回滚以外的另一个作用是MVCC,若记录被其他事务占用,当前事务可以通过undo读取之前的行版本信息,以此实现非锁定读。

undo log会产生redo log,因为undo log也需要持久性的保护。

事务提交后不能马上删除undo log及undo log所在的页,因为可能还有其他事务需要通过undo log得到行记录之前的版本。事务提交时会将undo log放入一个链表,是否可删除由purge线程来判断。

purge

DELETE FROM t WHERE a=1;

DELETE操作仅是将主键列中等于1的记录delete flag设为1,记录还存在在B+树上。purge用于最终完成delete和update操作,因为MVCC所以记录不能立即处理。若该行记录已经不被其他任何事务引用,那么就可以进行真正的DELETE操作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章