《Mysql必读MSSQL产生死锁的根本原因及解决方法》要点:
本文介绍了Mysql必读MSSQL产生死锁的根本原因及解决方法,希望对您有用。如果有疑问,可以联系我们。
一、 什么是死锁
MYSQL入门
死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统发生了死锁,这些永远在互相等的进程称为死锁进程.
MYSQL入门
二、 死锁产生的四个需要条件
MYSQL入门
•互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用.如果此时还有其它进程哀求资源,则哀求者只能等待,直至占有资源的进程用毕释放
MYSQL入门
•哀求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源哀求,而该资源已被其它进程占有,此时哀求进程阻塞,但又对自己已获得的其它资源保持不放
MYSQL入门
•不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由本身释放
MYSQL入门
•环路等待条件:指在产生死锁时,必然存在一个进程――资源的环形链,即进程集合{P0,P1,P2,・・・,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源
MYSQL入门
这四个条件是死锁的需要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁.
MYSQL入门
三、 如何处理死锁
MYSQL入门
1) 锁模式
MYSQL入门
1.共享锁(S)
MYSQL入门
由读操作创建的锁,防止在读取数据的过程中,其它事务对数据进行更新;其它事务可以并发读取数据.共享锁可以加在表、页、索引键或者数据行上.在SQL SERVER默认隔离级别下数据读取完毕后就会释放共享锁,但可以通过锁提示或设置更高的事务隔离级别改变共享锁的释放时间.
MYSQL入门
2.独占锁(X)
MYSQL入门
对资源独占的锁,一个进程独占地锁定了哀求的数据源,那么别的进程无法在此数据源上获得任何类型的锁.独占锁一致持有到事务结束.
MYSQL入门
3.更新锁(U)
MYSQL入门
更新锁实际上并不是一种独立的锁,而是共享锁与独占锁的混合.当SQL SERVER执行数据修改操作却首先必要搜索表以找到必要修改的资源时,会获得更新锁.
MYSQL入门
更新锁与共享锁兼容,但只有一个进程可以获取当前数据源上的更新锁,
MYSQL入门
其它进程无法获取该资源的更新锁或独占锁,更新锁的作用就好像一个序列化阀门(serialization gate),将后续申请独占锁的哀求压入队列中.持有更新锁的进程能够将其转换成该资源上的独占锁.更新锁不足以用于更新数据―实际的数据修改仍需要用到独占锁.对于独占锁的序列化访问可以避免转换死锁的发生,更新锁会保留到事务结束或者当它们转换成独占锁时为止.
MYSQL入门
4. 意向锁(IX,IU,IS)
MYSQL入门
意向锁并不是独立的锁定模式,而是一种指出哪些资源已经被锁定的机制.
MYSQL入门
如果一个表页上存在独占锁,那么另一个进程就无法获得该表上的共享表锁,这种层次关系是用意向锁来实现的.进程要获得独占页锁、更新页锁或意向独占页锁,首先必需获得该表上的意向独占锁.同理,进程要获得共享行锁,必需首先获得该表的意向共享锁,以防止别的进程获得独占表锁.
MYSQL入门
5. 特殊锁模式(Sch_s,Sch_m,BU)
MYSQL入门
SQL SERVER提供3种额外的锁模式:架构稳定锁、架构修改锁、大容量更新锁.
MYSQL入门
6.转换锁(SIX,SIU,UIX)
MYSQL入门
转换锁不会由SQL SERVER 直接哀求,而是从一种模式转换到另一种模式所造成的.SQL SERVER 2008支持3种类型的转换锁:SIX、SIU、UIX.其中最常见的是SIX锁,如果事务持有一个资源上的共享锁(S),然后又需要一个IX锁,此时就会出现SIX.
MYSQL入门
7.键范围锁
MYSQL入门
键范围锁是在可序列化隔离级别中锁定必定范围内数据的锁.保证在查询数据的键范围内不允许插入数据.MYSQL入门
SQL SERVER 锁模式MYSQL入门 |
||
缩写MYSQL入门 |
锁模式MYSQL入门 |
阐明MYSQL入门 |
SMYSQL入门 |
SharedMYSQL入门 |
允许其他进程读取但不克不及修改锁定的资源MYSQL入门 |
XMYSQL入门 |
ExclusiveMYSQL入门 |
防止其余进程读取或者修改锁定资源中的数据MYSQL入门 |
UMYSQL入门 |
UpdateMYSQL入门 |
防止其它进程获取更新锁或独占锁;在搜索要修改的数据时使用MYSQL入门 |
ISMYSQL入门 |
Intent sharedMYSQL入门 |
表现该资源的一个组件被共享锁锁定了.只有在表或页级别才能获得这类锁MYSQL入门 |
IUMYSQL入门 |
Intent updateMYSQL入门 |
表现该资源的一个组件被更新锁锁定了.只有在表或页级别才能获得这类锁MYSQL入门 |
IXMYSQL入门 |
Intent exclusiveMYSQL入门 |
表现该资源的一个组件被独占锁锁定了.只有在表或页级别才能获得这类锁MYSQL入门 |
SIXMYSQL入门 |
Shared with intent exclusiveMYSQL入门 |
表现一个正持有共享锁的资源还有一个组件(一页或一行)被独占锁锁定了MYSQL入门 |
SIUMYSQL入门 |
Shared with intent UpdateMYSQL入门 |
表现一个正持有共享锁的资源还有一个组件(一页或一行)被更新锁锁定了MYSQL入门 |
UIXMYSQL入门 |
Update with intent exclusiveMYSQL入门 |
表现一个正持有更新锁的资源还有一个组件(一页或一行)被独占锁锁定了MYSQL入门 |
Sch-SMYSQL入门 |
Schema stabilityMYSQL入门 |
表现一个使用该表的查询正在被编译MYSQL入门 |
Sch-MMYSQL入门 |
Schema modificationMYSQL入门 |
表现表的结构正在被修改MYSQL入门 |
BUMYSQL入门 |
Bulk UpdateMYSQL入门 |
在一个大容量复制操作将数据导入表中而且(手动或自动)应用了TABLOCK查MYSQL入门 询提示时使用MYSQL入门 |
2) 锁粒度
MYSQL入门
SQL SERVER 可以在表、页、行等级别锁定用户的数据资源即非系统资源(系统资源是用闩锁来掩护的).此外SQL SERVER 还可以锁定索引键和索引键范围.
MYSQL入门
通过sys.dm_tran_locks视图可以查看谁被锁定了(如行,键,页)、锁的模式以及特定资源的标记符.基于sys.dm_tran_locks视图创建如下视图用于查看锁定的资源以及锁模式(通过这个视图可以查看事务锁定的表、页、行以及加在数据资源上的锁类型).
MYSQL入门
CREATE VIEW dblocks AS SELECT request_session_id AS spid, DB_NAME(resource_database_id) AS dbname, CASE WHEN resource_type='object' THEN OBJECT_NAME(resource_associated_entity_id) WHEN resource_associated_entity_id=0 THEN 'n/a' ELSE OBJECT_NAME(p.object_id) END AS entity_name, index_id, resource_type AS RESOURCE, resource_description AS DESCRIPTION, request_mode AS mode, request_status AS STATUS FROM sys.dm_tran_locks t LEFT JOIN sys.partitions p ON p.partition_id=t.resource_associated_entity_id WHERE resource_database_id=DB_ID()
3) 如何跟踪死锁
MYSQL入门
通过选择sql server profiler 变乱中的如下选项就可以跟踪到死锁产生的相关语句.
MYSQL入门
4) 死锁案例阐发
MYSQL入门
在该案例中process65db88, process1d0045948为语句1的进程,process629dc8 为语句2的进程; 语句2获取了1689766页上的更新锁,在等待1686247页上的更新锁;而语句1则获取了1686247页上的更新锁在等待1689766页上的更新锁,两个语句等待的资源形成了一个环路,造成死锁.
MYSQL入门
5) 如何办理死锁
MYSQL入门
针对如上死锁案例,阐发其对应语句执行计划如下:
MYSQL入门
通过执行计划可以看出,在查找需要更新的数据时使用的是索引扫描,比拟耗费性能,这样就造成锁定资源时间过长,增加了语句并发执行时产生死锁的概率.
MYSQL入门
处理方式:
MYSQL入门
1. 在表上建立一个聚集索引.
MYSQL入门
2. 对语句更新的相关字段建立包括索引.
MYSQL入门
优化后该语句执行计划如下:
MYSQL入门
优化后的执行计划使用了索引查找,将大幅提升该查询语句的性能,降低了锁定资源的时间,同时也减少了锁定资源的范围,这样就降低了锁资源循环等待事件发生的概率,对于预防死锁的发生会有必定的作用.
MYSQL入门
死锁是无法完全避免的,但如果应用程序适当处理死锁,对涉及的任何用户及系统别的部分的影响可降至最低(适当处理是指发生错误1205时,应用程序重新提交批处理,第二次尝试大多能成功.一个进程被杀死,它的事务被取消,它的锁被释放,死锁中涉及到的另一个进程就可以完成它的工作并释放锁,所以就不具备产生另一个死锁的条件了.)
MYSQL入门
四、 如何预防死锁
MYSQL入门
阻止死锁的途径就是避免满足死锁条件的情况发生,为此我们在开发的过程中必要遵循如下原则:
MYSQL入门
1.尽量避免并发的执行涉及到修改数据的语句.
MYSQL入门
2.要求每一个事务一次就将所有要使用到的数据全部加锁,不然就不允许执行.
MYSQL入门
3.预先规定一个加锁顺序,所有的事务都必须依照这个顺序对数据执行封锁.如不同的过程在事务内部对对象的更新执行顺序应尽量保证一致.
MYSQL入门
4.每个事务的执行时间弗成太长,对程序段的事务可考虑将其分割为几个事务.在事务中不要求输入,应该在事务之前得到输入,然后快速执行事务.
MYSQL入门
5.使用尽可能低的隔离级别.
MYSQL入门
6.数据存储空间离散法.该方法是指采用各种手段,将逻辑上在一个表中的数据分散的若干离散的空间上去,以便改善对表的访问性能.主要通过将大表按行或者列分解为若干小表,或者依照不同的用户群两种方法实现.
MYSQL入门
7.编写应用法式,让进程持有锁的时间尽可能短,这样其它进程就不必花太长的时间等待锁被释放.
MYSQL入门
维易PHP培训学院每天发布《Mysql必读MSSQL产生死锁的根本原因及解决方法》等实战技能,PHP、MYSQL、LINUX、APP、JS,CSS全面培养人才。