TENCHIANG / blog

issue blog
10 stars 1 forks source link

事务的ACID属性 #54

Open TENCHIANG opened 5 years ago

TENCHIANG commented 5 years ago

事务(Transaction)指的是满足 ACID 特性的一组操作,可以通过 Commit 提交一个事务,也可以使用 Rollback 进行回滚。

ACID分别是:原子性(atomicity,或称不可分割性)、一致性(consistency)、隔离性(isolation,又称独立性)、持久性(durability)。

A: 原子性(Atomicity,或称不可分割性)

一个事务包含多个操作视为一个原子整体,事务内所有操作要么全部完成,要么某一个操作失败而整个事务失败并回滚(Rollback),就像没有执行过事务一样,不能只执行其中一些操作。 回滚可以用回滚日志来实现,回滚日志记录着事务所执行的修改操作,在回滚时反向执行这些修改操作即可。

C: 一致性(Consistency)

这里的一致性很容易搞混,一致性有很多种一致性(他们都互不相同):

  1. 多副本的一致性
  2. 一致性hash
  3. CAP理论的一致性
  4. ACID里的一致性

ACID的一致性,可以理解为应用系统从一个正确的状态到另一个正确的状态。而ACID就是说事务能够通过AID来保证这个C的过程,C是目的,AID都是手段。

I: 隔离性(Isolation,又称独立性)

事务之间互相影响的程度或者说事务间的可见性(特别是并发任务),比如一个事务会不会读取到另一个未提交的事务修改的数据。

事务在并发情况下可能会出现的问题

一致性和并发性能不可兼得,在实际应用中应做一些取舍,适当的破坏一致性来提升性能与并行度,这就是

隔离级别(Isolation level)

隔离级别严格程度由低到高 隔离级别的特性就是它的问题,它的问题就是它的特性

  1. 未提交读(Read uncommitted) 一个事务可以读到另一个事务未提交或已撤销的结果(脏读)。所有的并发事务问题都会发生。 事务未提交和已撤销是一个东西。

  2. 提交读(Read committed) 一个事务只能读取已经提交的事务所做的修改 -> 一个事务所做的修改在提交之前对其它事务是不可见的 -> 两次查询可能会得到不一样的结果(因为别的事务的提交),所以又称 不可重复读 可以解决脏读问题。 大部分数据库默认的隔离级别是 提交读,MySQL是 可重复读。

  3. 可重复读(Repeatable read) 保证在同一个事务中多次读取同样数据的结果是一样的,无论是否有其他事务对这份数据进行操作,以及这个事务是否提交。可以解决脏读、不可重复读,但是不能解决 幻读(Phantom read) 。 InnoDB和XtraDB存储引擎可通过 多版本并发控制(MVCC, Multiversion Concurrency Control) 解决幻读问题。

  4. 串行化(Serializable) 事务串行化执行,隔离级别最高,牺牲了系统的并发性。可以解决并发事务的所有问题。 需要加锁实现,而其它隔离级别通常不需要(所谓加锁读?)。

隔离级别越低,并发性越好,系统开销越低,因为要做的操作或者约束越少。

隔离级别 脏读 不可重复读 幻读 加锁读
未提交读 ☑️ ☑️ ☑️ ✖️
提交读 ✖️ ☑️ ☑️ ✖️
可重复读 ✖️ ✖️ ☑️ ✖️
串行化 ✖️ ✖️ ✖️ ☑️

D: 持久性(Durability)

事务一旦提交,那么就会执行成功永久生效,或者发生错误回滚如初,不会因为数据库崩溃而改变。 使用重做日志来保证持久性。 持久性也分很多种级别。