概念
ACID:Atomicity(原子性)、Consistency(一致性)、Isolation(隔离性)、Durability(持久性)。
隔离级别
SQL 标准的事务隔离级别包括:读未提交(read uncommitted)、读提交(read committed)、可重复读(repeatable read)、串行化(serializable)。
下面的表格从自己和他人的视角分别描述这四个隔离级别:
隔离级别 | 自己视角 | 他人视角 |
---|---|---|
读未提交 read uncommitted |
我可以读到其他事务中 尚未提交 的数据修改 | 自己的事务提交 前,我对数据的变更就可以被他人看到 |
读提交 read committed |
我不能读到其他事务中 尚未提交 的数据修改 我可以读到其他事务中 已经提交 的数据修改 |
自己的事务提交 后,我对数据的变更才可以被他人看到 |
可重复读 repeatable read |
在我的事务执行过程中,任何时刻看到的任何数据都和启动事务时看到的一致 注:启动事务指第一条 SQL 执行时,非 start transaction 语句 |
自己的事务提交 后,我对数据的变更才可以被他人看到 |
串行化 serializable |
在我操作的任何行数据上,读加读锁,写加写锁,任何人和我的锁冲突了都要等待我完成才行 | 自己的事务提交 后,我对数据的变更才可以被他人看到 存在锁冲突的情况下,那么会一直阻塞别人的语句执行 |
隔离级别实现方式
数据库会通过 InnoDB 的一致性视图的方式来满足各个隔离级别的不同要求。
- 读未提交(read uncommitted):没有视图的概念,每条 SQL 会直接返回记录上的最新值
- 读提交(read committed):在每条 SQL 语句执行前都会创建一个新的视图,所以在读提交的级别下,一个事务可以看到另外一个事务已经提交的内容,因为在每次查询之前都会重新给最新的数据创建一个新的视图
- 可重复读(repeatable read):视图在事务启动时(第一条语句执行)创建,整个事务存在期间都用这个视图
- 串行化(serializable):没有视图的概念,通过直接加锁的方式避免并行访问
多事务同时执行的时候,可能发生的问题
脏读
当数据库中一个事务 A 正在修改一个数据但是还未提交或者回滚,另一个事务 B 来读取了修改后的内容并且使用了, 之后事务 A 提交了,此时就引起了脏读。
此情况仅会发生在: 读未提交的的隔离级别
不可重复读
在一个事务 A 中多次操作数据,在事务操作过程中(未最终提交)事务 B 也做了处理,并且该值发生了改变,这时候就会导致 A 在事务操作的时候,发现数据与第一次不一样了,就是不可重复读。
此情况仅会发生在:读未提交、读提交的隔离级别
幻读
一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为幻读。
幻读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的“全部数据行”。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入“一行新数据”。那么,以后就会发生操作第一个事务的用户发现表中还存在没有修改的数据行,就好象发生了幻觉一样。
一般解决幻读的方法是增加范围锁,锁定检索范围为只读,这样就避免了幻读。
此情况会发生在:读未提交、读提交、可重复读的隔离级别