我在查询维基百科的时候,他给了这么句话:“Any deadlock situation can be compared to the classic "chicken or egg" problem.”。于是,这个曾经困扰我很多天的经典的案例就在死锁中出现了。
【基础知识】
1.什么是死锁?
这是一个老生常谈的问题。
百度百科给出的官方解释是:
集合中的每一个进程都在等待只能由本集合中的其他进程才能引发的事件,那么该组进程是死锁的。 之A前听师哥讲的时候:A在501机房,手里拿着511的钥匙;B在511机房,手里拿着501的钥匙;当A想访问B,B想访问A的时候,就产生了死锁。
2. 产生死锁的四个必备条件
虽然进程在运行过程中,可能发生死锁,但死锁的发生也必须具备一定的条件,死锁的发生必须具备以下四个必要条件。
1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
3)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
4)环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。
【关于师哥的博客的理解】
在师哥写的高并发update的 死锁产生原因:http://blog.csdn.net/zc474235918/article/details/50547250 。感觉理解了好久,大体是这个意思:
我理解的大体意思是这样子的:
首先数据库是自带锁的,当事务进行查询的时候,如果没有加上聚集索引神马的,是把所有的数据都加上U型锁,一个一个去验证,如果不是自己数据,那么便释放资源,如果是自己要的那条数据,U型锁则变成X型锁。
现在A事务执行两条更新语句,第二条事务执行一条更新语句,为了模拟当时一级考试出现的高并发的现象, 执行A事务的时候waitfor delay '00:00:05'这样子A执行完第一条语句之后,并没有立马执行下一句话,而是处于等待状态。所以执行B的事务,当B运行到A占据的资源的时候,也处于等待状态,当B找到自己的资源的时候,同样加上改为X锁,当A事务释放资源继续执行第二条语句,同样是站着一个资源等待一个死锁。这样死锁就出现了。
1. 聚集索引能够解决死锁?
其实我上面这句话本身是很有问题的,首先,聚集索引不能解决死锁,只能是降低死锁发生的概率。后来我在反复看师哥一篇关于索引博客的时候发现了一句:聚集索引就是把很大范围内迅速缩小范围来查找。我琢磨了半天,才了解:
首先数据库是自带锁的,当事务进行查询的时候,如果没有加上聚集索引神马的,是把所有的数据都加上U型锁,一个一个去验证,如果不是自己数据,那么便释放资源,如果是自己要的那条数据,U型锁则变成X型锁。
通过聚集索引来缩小范围,这样子执行事务A的时候并不用把所有的数据都上U锁,也就说A事务,B事务搜索的范围不一样,这样子,产生死锁的概率就会大大降低。