Database

事务的ACID特性

事务的定义

一系列对数据进行访问与更新的操作组成的执行单元。狭义的事务指数据库事务。

事务的四个特征

1. 原子性(Atomicity)

  • 事务的全部操作要么全部执行成功,要么全部失败
  • 如果事务中的某个操作失败,其他的操作也必须回滚

2. 一致性(Consistency)

  • 事务执行前后,数据均处于一致的状态

数据一致的标准是由具体业务来定义的,如

  • 银行系统在内部转账时,钱的总数保持不变
  • 数据存储了多个副本,更新操作保证每个副本的值均一致

事务执行过程中,数据可能处于不一致的状态;执行完成之后,数据必须在一致的状态。

3. 隔离性(Isolation)

  • 并发执行的事务之间不会互相干扰
  • 每个事务有各自完整的数据空间

4. 持久性(Durability)

  • 事务一旦提交,对数据的变更时永久的
  • 即便出现系统崩溃,在重新启动后依旧能恢复事务成功结束时的状态

一致性级别

1. 强一致

事务提交后,立即可以读取提交的改动

2. 弱一致

无法立即读取事务的变更,但在一定时间窗口后可以读取变更

3. 最终一致

弱一致的特殊形式,在没有新的更新情况下,最终所有访问都会读取到最后一次更新的值

如果事务满足最终一致,它就属于弱一致。验证最终一致的特殊场景是不再发生新的更新

事务隔离级别

标准SQL规范中,由弱到强的四个级别

1. 读未提交(Read Uncommitted)

一个事务对数据进行变更尚未提交,另一个事务能够读取到该变更。此时会产生脏读,如

  • A事务对x用户减100元、y用户加100元
  • B事务能够读取到x用户已经减了100元,但y用户的金额未改变

2. 读已提交(Read Committed)

事务必须读取已提交的变更,但在一个事务中可能读取到多个已提交的变更,出现不可重复读,如

  • A事务将x账户更新为100元,B事务首先读取到账户余额为100元
  • B事务执行完成之前,C事务将x账户余额更新为200元,此时B事务再去读取x账户,发现余额变成了200元

一次B事务中从x账户读取到了两次不一样的值。

3. 可重复读(Repeatable Read)

保证在一次事务中,对某一数据的全部读取均得到相同的值。

可重复读有两种实现方式

锁模式

在事务执行过程中,对已读取的数据添加读锁,允许其他事务读取,但不允许修改

  • A事务将x账户更新为100元,B事务首先读取到账户余额为100元
  • B事务执行完成之前,将x账户更新为200元的C事务无法提交(阻塞等待),B事务再次读取余额仍是100元
  • B事务提交后,C事务进行提交
快照模式

为事务中读取的数据建立快照(Read View),之后的读操作通过快照完成。

  • A事务将x账户更新为100元,B事务首先读取到账户余额为100元,此时B事务为x账户创建一个快照
  • B事务执行完成之前,C事务将x账户余额更新为200元,B事务从快照读取余额仍是100元

快照模式相对锁模式可以避免在访问大量数据时大批量地加锁。

幻读

对于存在批量查询或更新的事务,如果中途其他事务插入或删除数据,会出现幻读现象

  • A事务查询余额小于100元的用户,得到3个用户
  • B事务新插入了一个余额小于100元的用户
  • A事务将余额小于100元的账户冻结,发现影响了4个用户

4. 串行化(Serilizable)

所有事务串行执行,一个事务结束后才能开始下一个事务,不能并发处理。

  • A事务查询余额小于100元的用户,得到3个用户
  • 此时插入数据的B事务无法执行
  • A事务将余额小于100元的账户冻结,影响了3个用户
  • A事务提交后,B事务再执行插入用户的操作

MySQL InnoDB的默认实现

  • 默认事务隔离级别是可重复读
  • 默认可重复读的实现方式是快照模式

© 2018, 高飞航.cn. 版权所有.

发表评论

电子邮件地址不会被公开。 必填项已用*标注