MySQL--ACID特性(10)

67 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第41天,点击查看活动详情

ACID特性

在关系型数据库管理系统中,一个逻辑工作单元要成为事务,必须满足这 4 个特性,即所谓的 ACID:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。

1.原子性

原子性:事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行。

image.png

每写一个事务,都会修改Buffer Pool,从而产生响应的Redo/Undo日志:

  • 如果事务提交之后,redo log刷入磁盘,结果MySQL宕机了,是可以根据redo log恢复事务修改过的缓存数据的。
  • 如果要回滚事务,那么就基于undo log来回滚就可以了,把之前对缓存页做的修改都给回滚了就可以了。

2.持久性

持久性:指的是一个事务一旦提交,它对数据库中数据的改变就应该是永久性的,后续的操作或故障不应该对其有任何影响,不会丢失。

MySQL持久性的保证依赖两个日志文件: redo logbinlog

因为最开始MySQL没有InnoDB引擎,MySQL自带的引擎是MyISAM,但是MyISAM没有crash-safe的能力,binlog日志只能用于归档,InnoDB如果只依靠binlog是没有crash-safe能力的,所以InnoDB使用另外一套日志系统,redo log来实现crash-safe能力。

下图为 update 语句的执行流程图,图中白色框表示是在 InnoDB 内部执行的,绿色框表示是在执行器中执行的。

update T set c = c+1 where ID = 2

image.png

  1. 执行器先找引擎取 ID=2 这一行。ID 是主键,引擎直接用树搜索找到这一行。如果 ID=2 这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回。
  2. 执行器拿到引擎给的行数据,把这个值加上 1,比如原来是 N,现在就是 N+1,得到新的一行数据,再调用引擎接口写入这行新数据。
  3. 引擎将这行新数据更新到内存(InnoDB Buffer Pool)中,同时将这个更新操作记录到 redo log 里面,此时 redo log 处于 prepare 状态。然后告知执行器执行完成了,随时可以提交事务。
  4. 执行器生成这个操作的 binlog,并把 binlog 写入磁盘。
  5. 执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成。

两阶段提交

将 redo log 的写入拆成了两个步骤:prepare 和 commit,这就是两阶段提交(2PC)。

image.png

为什么使用两阶段提交 ?

MySQL 使用两阶段提交主要解决 binlog 和 redo log 的数据一致性的问题。

当进行 crash recovery 时, redo log 和 binlog 有一个共同的数据字段,叫 XID。崩溃恢复的时候,会按顺序扫描 redo log:

  • 如果碰到既有 prepare、又有 commit 的 redo log,就直接提交.

  • 如果 redo log 处于 prepare,就拿着 XID 去 binlog 找对应的事务, 判断事务对应的 binlog 是不是完整的.

    • 是,则把事务提交
    • 否,则事务回滚

持久性的保证

  • redo log在系统Crash重启之类的情况时,可以修复数据,从而保障事务的持久性.
  • 通过原子性可以保证逻辑上的持久性.
  • 通过存储引擎的数据刷盘可以保证物理上的持久性.

3.隔离性

隔离性:指的是一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对其他的并发事务是隔离的。

不考虑隔离性会引发的问题:

  • 脏读 : 一个事务读取到了另一个事务修改但未提交的数据。
  • 不可重复读: 一个事务中多次读取同一行记录的结果不一致,后面读取的跟前面读取的结果不一致。
  • 幻读 : 一个事务中多次按相同条件查询,结果不一致。后续查询的结果和面前查询结果不同,多了或少了几行记录。

InnoDB 支持的隔离性有 4 种,隔离性从低到高分别为:读未提交、读提交、可重复读、可串行化。锁和多版本控制(MVCC)技术就是用于保障隔离性的(后面课程详解)。

4.一致性

一致性:指的是事务开始之前和事务结束之后,数据库的完整性限制未被破坏。一致性包括两方面的内容,分别是约束一致性和数据一致性。

  • 约束一致性:创建表结构时所指定的外键、Check、唯一索引等约束,可惜在 MySQL 中不支持 Check 。
  • 数据一致性:是一个综合性的规定,因为它是由原子性、持久性、隔离性共同保证的结果,而不是单单依赖于某一种技术。

一致性也可以理解为数据的完整性。数据的完整性是通过原子性、隔离性、持久性来保证的,而这3个特性又是通过 Redo/Undo 来保证的。逻辑上的一致性,包括唯一索引、外键约束、check 约束,这属于业务逻辑范畴。

image.png

5.ACID的关系

  • 事务的持久化是为了应对系统崩溃造成的数据丢失.
  • 只有保证了事务的一致性,才能保证执行结果的正确性
  • 在非并发状态下,事务间天然保证隔离性,因此只需要保证事务的原子性即可保证一致性.
  • 在并发状态下,需要严格保证事务的原子性、隔离性。

image.png