0
点赞
收藏
分享

微信扫一扫

【SQL Server】数据库死锁

小a草 04-15 06:00 阅读 1
数据库

         在软件使用了SQL Server数据库的场合,运行软件时,出现:
"事务(进程 ID **)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事物"。

        分析原因:软件多个进程在调用SQL语句访问数据库表的场合,因为资源互相占用,产生的死锁。

         例如:
         用户A,访问了表1,同时要更新表2。
         用户B,访问了表2,同时要更新表1。
由于用户A访问表1的场合,锁住了表1。用户B访问表2的场合,锁住了表2。用户A等待用户B释放表2。用户B等待用户A释放表1。

         又例如:

          用户A事务访问了表1,A对表1有共享锁。A在读完表1之后,需要对表1进行修改,即需要由共享锁到独占锁。

         而用户B事务对表1享有独占锁。B必须在A释放共享锁之后,才能释放独占锁。然后A必须在B释放独占锁之后才能对表1取得独占锁。

           故形成了死锁。

          解决方法:主体思想为:避免死锁。

         1)避免两个进程同时锁定两个资源。

         2)已经同时锁定资源的场合,按照一定的顺序释放资源。

・在select 语句上加上NOLock语句。如:select * from table1 with(NOLock)

解释:加上With(NoLock)后,SELECT不对查询到的资源加锁(或者加Sch-S锁,Sch-S锁可以与任何锁兼容)。因此两个事物可以同时访问同一张表。适合解决:读与写并发死锁的情况。缺点是:导致脏读。

・在select语句之前加上语句:SET TRANSACTION ISOLATION LEVEL。
解释:语句可以读取已由其他事务修改但尚未提交的行。缺点是:导致脏读。

・事务中使用快照隔离。

SET ALLOW_SNAPSHOT_ISOLATION ON

SET READ_COMMITTED_SNAPSHOT ON

解释:使用基于行版本控制的隔离级别(SQL Server 2005支持):开启上面的选项后,SELECT不会对请求的资源加S锁,不加锁或者加Sch-S锁,从而将读与写操作之间发生的死锁几率降至最低;而且不会发生脏读。



                        
 

举报

相关推荐

0 条评论