1、死锁产生的原因:
a.系统资源不足
b.进程拿锁的顺序不当
c.资源分配不当
2、死锁产生的四个条件
a.互斥条件:进程在某一时刻独占一个资源,反过来讲,就是一个资源在某一时间内只能被一个进程占有,不能被两个或两个以上的进程占有。
b.占有且申请条件:进程至少占有一个资源,但又申请新的资源,由于该资源已经被另外进程占有,此时该进程阻塞。但是,它在等待申请新的资源时,仍然不释放已占有的资源。也即,一个进程因请求资源而阻塞时,对已经获取的资源保持不放。
c.不可抢占资源:进程已经获得资源,在未使用完之前,资源申请者不能强行从资源自由者手中夺取资源,而只能由资源占有者进程自行释放。
d.循环等待条件:若干进程之间形成一种手尾相接的循环等待资源关系。
3、如果避免死锁
a.按顺序拿锁
b.可以中断
c.设置获取锁的时间,如果获取不到,自动退出
4、数据库预防死锁的方式
a.尽量避免并发的执行涉及到修改数据的语句
b.要求每个事务一次就将所有要使用的资源全部加锁,否则不予执行
c.预先规定一个封锁机制,所有的事务都必须按照这个顺序对数据执行加锁。比如,不同的过程在事务内部对对象的更新顺序应尽量保持一致。
d.每个事务的执行时间不可太长,在业务允许的情况下,可以考虑将事务分割成几个小事务来执行。比如一个复杂的多表查询,分割成多次单表查询。
e.分库分表,主要是将大表分解成若干小表,或者按照不同的用户分解。
f.读写分离
g.尽可能的使用较低级别的隔离机制。如Read Uncommited。因为隔离级别越低,事务之间相互等待的情况会更少,这样每个事务都会尽可能的完成数据库操作,然后释放其拥有的资源锁,这样就会减少锁等待或者死锁的概率。但是要考虑事务不一致的情况。
在MySql的InnoDB中,锁是通过加载索引上来实现的。Mysql中通过一种循环依赖检测机制来实现了对死锁的检测。比如,session1为了执行第一次更新,锁住了a=1 and b=2这个索引节点。session2为了更新,必须等待session1释放锁。session1再执行一次更新,那么数据库就会检测到这种死锁的存在,不用等到timeout,直接退出了。