5分钟真正理解mysql事务隔离级别和封锁协议

排他锁和共享锁

1.排他锁的作用范围是:执行语句开始,到在事务提交时才会释放。

2.本事务对某数据加了排他锁,则其他事务就不能对该数据加任何锁(包括排他锁和共享锁)。

3.本事务对某数据加了共享锁,则其他事务也可以对该数据加共享锁。

四个隔离级别

1.Read Uncommitted(读取未提交内容)。其现象为脏读,即可以读取到其他事务未提交的数据。

【例子1】:有两个事务同时开始,两者都在10秒后执行完毕,提交事务。a事务在3秒时改了一条数据,b事务在5秒时读取该数据,读取到的是被a事务改了之后的值。 使用二级封锁协议可以避免脏读。

2.Read Committed(读取已提交内容)。其现象为不可重复读。使用二级封锁协议虽然避免脏读的问题了,读不到未提交的数据了,但是能在自身事务执行过程中,读到这期间内其他事务已提交的数据。使用三级封锁协议可以避免脏读和不可重复读。

【例子2】:两个事务同时开始,b在第3秒改了一条数据,如果启用二级封锁协议,则a在它改之后也是读不到这条数据的变更的,但是在第5秒b提交了自己的事务,然后此时a就在自己的事务还没提交的情况下就读到了b提交的变更。 

3.Repeatable Read(可重复读)。可重复读的意思就是在一个事务里读同一条记录,读多少次都是一样的结果,不受其他事务干扰。使用三级封锁协议就可以做到可重复读,但是它避免不了幻读现象。需要串行化才能避免幻读。

【例子3】:举一个幻读的例子,在a事务中首次查询到了3条数据,然后b事务新增了1条数据,使得a事务中的查询再次执行时,结果变多了1条。

4.Serializable(串行化)。可以避免脏读不可重复读和幻读,不会出现并发问题了。

注意:4种隔离级别的定义来自sql92标准。而具体各个db的实现其实各不相同。

下面说的是mysql的实现:

mysql各级别封锁协议具体原理?

1.启用一级封锁协议时,在【例子1】中,a事务在第3秒改数据时,因为是改数据,所以会自动加上排他锁,然后因为一级封锁协议下查询是不加任何锁的,所以b事务可以查到数据。可以说根本没有隔离没有封锁,这个状态,就是个事务最最基础状态,在事务出问题的情况下可以回滚,可以保证事务中的修改,在提交时会生效。

2.启用二级封锁协议时,此时a改数据依然是加的排他锁,b查数据仅在查询发起到查询返回数据这短暂的时间加共享锁,查到之后锁立即解除,不会等到事务提交。所以由于a的排他锁是事务提交时才会解除,所以在a提交之前,b都查不到数据的,查数据就会阻塞。这就是为什么事务尤其是更新数据的事务不可以开启太长时间的原因啦,服务器搞不好都会挂掉。如果b先查询了一次,然后a修改数据之后提交,然后b再查数据,那肯定可以加上共享锁也就可以查到a提交之后的数据啦。

3.启用三级封锁协议时,b事务如何能够保证从自己开启到结束时,自己想查的数据都不会被改变呢?只有对相关数据加共享锁了,而且是直到本事务提交才释放。这样因为更新操作需要加排他锁,而已经有共享锁的情况下排他锁是加不成的,所以读事务是可以把写事务阻塞住的。当然了,sql执行时我们才会知道这是啥事务,锁定的是啥表。所以我推断,在a事务开启但是尚未执行查询sql时,尚未给数据加共享锁,那么此时b事务是可以修改数据并且提交的,如果在提交之后,a事务才开始执行查询,是可以查到b事务提交的数据的。不过这并没有违反可重复读,因为b事务提交之后,a事务开始第一次查询啊,而且之后的每次查询,都是相同的结果。所以我的推断应该是成立的,三级封锁协议只是比二级封锁协议多了一个规则:事务中的查询加共享锁。

4.串行化,比三级封锁协议还狠。前面的一二三级封锁协议都是在行级加锁,而串行化是对整表加锁。读数据时对整表加共享锁,修改数据对整表加排他锁。


感谢以下文章帮助我理解:

https://blog.csdn.net/p10010/article/details/50283255

https://blog.csdn.net/tolcf/article/details/49311035

关于pgsql的实现,可以看看这篇:http://www.xuebuyuan.com/1449647.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值