事务ACID的实现

来源:互联网 发布:淘宝食品安全怎么填写 编辑:程序博客网 时间:2024/05/22 13:55

事务需要满足ACID特性,那在数据库中,它是如何实现的?我们接下来的内容将一一介绍。

1.隔离性

其实我们在《MySQL InnoDB引擎 MVCC并发控制》中谈到了事务的隔离级别,但没有谈到怎样实现隔离性。我们提到了要消除幻读,一般的数据库系统需要保证串行化的事务隔离级别,而MySQL InnoDB在可重复读的事务隔离级别下消除了幻读,功劳应该归于Next-key Lock锁。这个具体详述在《MySQL InnoDB中的行锁 Next-Key Lock消除幻读》。那说了半天事务隔离级别,隔离性到底是如何实现的?其实在上面我们已经谈到了,是锁机制+MVCC。我们通过MVCC使得事务隔离级别达到了可重复读,使用锁机制消除了幻读,实现了事务隔离。需要注意的是,在使用分布式事务时,InnoDB存储引擎的事务隔离级别必须设置为串行化。

2.持久性和原子性

通过数据库的redo log重做日志,来保证事务的持久性与原子性。

2.1 持久性

重做日志由两部分组成:重做日志缓冲(内存)和重做日志文件(物理存储)。当事务提交(commit)时,必须先将该事务的所有日志写入到重做日志文件进行持久化,待事务提交操作完成才算完成。redo log重做日志基本上都是顺序写的。为了确保每次日志都写入重做日志文件,在每次将重做日志缓存写入重做日志文件后,InnoDB存储引擎都需要调用一次fsync(文件同步)操作。当然MySQL提供一些参数来调整缓冲刷新到文件的策略,在这里就不细讲了。

2.2 原子性

在InnoDB存储引擎中,重做日志都是以512字节进行存储的,称为重做日志块。若一个页中产生的重做日志数量大于512字节,那么需要分割为多个重做日志块进行存储。由于重做日志块的大小与磁盘扇区大小一样,都是512字节,因此重做日志的写入可以保证事务的原子性。重做日志块大小为512字节,但其中包含的有效存储为492字节,重做日志文件头占12字节,日志尾占8字节。

3. 一致性

通过数据库的undo log撤销日志,来保证事务的一致性。
为了完成事务的回滚操作,在对数据库进行修改时,InnoDB存储引擎不但会产生redo log,还会产生一定量的undo logo。undo log是逻辑日志,只是将数据库逻辑地恢复到原来的样子,保证了事务的一致性(从一个状态转换为下一个一致性状态)。

3.1 redu和undo的区别

redo恢复提交事务修改的页操作,undo回滚行记录到某个特定版本。
redo通常是物理日志,记录的是页的物理修改操作。undo是逻辑日志,根据每行记录进行记录。

3.2 undo误解

通常对undo的误解是undo用于将数据库物理地恢复到执行语句或事务之前的样子。事实上,NO!!!

举个栗子:一个事务在修改当前一个页中某几条记录,同时还有别的事务在对同一个页中另几条记录进行修改。因此,不能将一个页回滚到事务开始的样子,因为这样会影响其他事务正在进行的工作。所以,在上面我们说道undo log是逻辑日志。

3.3 undo作用

除了回滚操作,undo的另一个作用是MVCC,在InnoDB存储引擎中MVCC的实现是通过undo来完成。当用户读取一行记录时,若该记录已经被其他事务占用,当前事务可以通过undo读取之前的行版本信息,以此实现非锁定读。
undo log会产生redo log,undo操作需要持久性保护。

参考:

  • 《MySQL技术内幕》
0 0