Isolation 隔离级别

Isolation (database systems) WIKI

Isolation level/lock

write lock

read lock

range lock

Read Uncommitted

Read Committed

Repeatable Read

Serializable

Read phenomena(读数据时出现的问题)

用users表进行查询,下面的例子都是两个事务 T1 和 T2,T1执行查询,T2修改数据并提交。

users

id

name

age

1

Joe

20

2

Jill

25

Dirty reads

T1查询 => T2修改 => T1再查询 => T2提交

T1两次查询得到的结果不一样,因为读到了T2未提交的修改,如果T2回滚了,T1第二次读到的结果就是错的。

dd5KMg-233200

Non-repeatable reads

T1查询 => T2修改,提交 => T1再查询

T1这个事务里读到的同一行记录不一样。

NytiBk-234051

什么时候出现?

1,加锁控制并发的数据库里,不对SELECT加锁或者SELECT加锁后马上释放了会导致这种情况。

2,MVCC的数据库里,遇到版本冲突时不回滚事务会导致这种情况。

解决方法

1,加锁控制并发的数据库里,对SELECT加锁并且事务结束时再释放。

2,MVCC的数据库里,正常执行,只是T1在整个执行过程中读到的数据都是其开始时的快照,在提交时验证结果是否和串行执行T1 T2等价,不等价则T1回滚。

Phantom reads

Non-repeatable reads类似,可以算是一种特殊情况。

T1范围查询 => T2 新增或删除行的修改,提交 => T1再范围查询

xYWbN2-003957

发生这种情况是因为在执行SELECT ... WHERE进行范围查询是没有获取 range locks ,串行化可以解决这个问题。

PS:lost updates

https://codingsight.com/the-lost-update-problem-in-concurrent-transactions/

Why is it a “lost update” in the Read Committed Transactions example of Oracle documentation?

T1 读id=1的age为20 => T2 读id=1的age为20 => T1修改age=100 where id = 1 => T2修改age=200 where id = 1(要等待T1提交完) => T1提交 => T2提交

最终结果是T2提交的结果,T1执行成功但是其结果丢失了,咋一看即使串行执行也是这个效果,没什么问题,但是如果场景是售卖商品的话就有问题了,如下图,T1卖了2个把剩余个数置为10,T2卖了3个把剩余个数置为9,最终数据库里存的9,错误。

这里的关键是T1 T2最开始读的是同一个数据,但是T1提交完没有通知T2已经改了该数据(也可以说是T2没有意识到T1已经改了),T2以为自己还是在最开始的数据的基础上做的修改。

如何解决呢,还是加读锁,在Repeatable reads的级别可以解决,但是Read committed会出现这个问题。

rBow3s-200103

Isolation levels 隔离级别(解决上面说的问题)

Serializable

1,加锁控制并发的数据库里,读锁 写锁 范围锁(select时加范围锁),并且在事务结束时释放。

2,MVCC的数据库里,遇到版本冲突时回滚事务。

Repeatable reads

加锁控制并发的数据库里,读锁 写锁,并且在事务结束时释放。但不获取范围锁,所以会出现Phantom reads

Read committed

字面意思,就是读的都是committed的数据。

Repeatable reads相比,读锁SELECT之后会马上释放,而不是事务结束时释放。所以会出现Phantom readsNon-repeatable reads

由于有写锁,所以脏读Dirty reads场景里T1第二次读要等待T2结束完才能读,因为被加锁了。(是这样吧?写锁会禁止读吗?)

Read uncommitted

三种问题都会出现。

Last updated

Was this helpful?