第十章:第16节 MySQL进阶篇——Read Committed、Serializable隔离级别下锁效果模拟演示

更新于:2017-08-31 15:06:41

除了MySQL默认的“Repeatable Read”隔离级别,还有一个常用的“Read Committed(RC读取提交内容)”,在这个隔离级别下再做下演示:


1.png


1)重新开启两个cmd窗口


1.png


此时处于“Read Committed”隔离级别。


2)开启事务,左右两边执行普通不加锁的select语句。


1.png


3)(左边)先执行select加X锁,然后再执行(右边)的语句。


1.png


和“RR”隔离级别一样,只有(左边)提交事务以后(右边)才可以获取到锁,这个楠神不演示了。


一个事务(A)未提交,其他事务是看不到(A)事务修改的数据的,这个也不演示了。


我们直接去演示和“RR”隔离级别不一样的地方。


4)(左边)执行update,(右边)执行普通的select语句,然后(左边)commit提交,(右边)再次执行普通的select语句


1.png


(右边)虽然事务还没有结束,普通的select语句可以获取到最新的数据。这个地方就和“RR”隔离级别完全不一样了。普通的select语句只要是已提交事务修改的数据都能获取到。所以在“RC”隔离级别下,数据是不可重复读的。


再去看下最高级别的隔离——“Serializable


1.png


1)重新开启两个cmd窗口


1.png


此时处于“Serializable”隔离级别。


2)开启事务,左右两边执行普通不加锁的select语句。


1.png


3)当在(左边)执行select加X锁时


1.png


报错了“锁等待超时”,如果是在(右边)执行select加X锁呢:


1.png

依然报错。


为什么都会报错?只有一种解释,在“Serializable”隔离级别下普通的select语句默认加了“共享锁S”。


(左边)1先加了一个“共享锁S”,(右边)2也可以为相同的数据集加一个“共享锁S”。在“共享锁S”下,是不能加“排他锁X”,只有等到“共享锁S”全部解除了才能加“排他锁X”。


所以说,“Serializable”隔离级别虽说可以最高地确保数据安全,但它的弊端太大:读写太容易冲突,易产生死锁,并发性急剧下降


4)看下面的死锁


1.png


当(右边)4执行加排他锁时,由于(左边)事务没有结束,(左边)的共享锁依然存在,(右边)一直等待……


此时,(左边)5也要加排他锁,可由于(右边)事务没有结束,(右边)的共享锁也还在,那此时就会出现一种僵持状态。(右边)需要等待(左边)解除共享锁,(左边)也在等待(右边)解除共享锁,此时就产生了死锁。


(右边)的排他锁是先准备加的,所以MySQL就强制把(左边)的事务结束了。


额外说明:


共享锁在事务结束时会解锁,当只有一个事务对某一数据集加“共享锁”,然后又加“排他锁”,是可以加成功的。“共享锁”会变成“排他锁”,事务自己肯定不会影响自己,事务的锁只会影响其他事务


在没有把握的情况下平时还是少用共享锁。


在写SQL语句时,要尽量避免死锁的产生。死锁后面还会重点讲解。


本节学习代码》》》