当前位置:文档之家› SQL SERVER数据库死锁处理及排查

SQL SERVER数据库死锁处理及排查

with max_rows_per_page=1 ● 在存储过程、触发器、动态 SQL 语句段中,若对某些整张表 select 操作较频繁,则可能在 该表上与其他访问该表的用户产生死锁。对于检查账号是否存在,但被检查的字段在检查期 间不会被更新等非关键语句,可以采用在 select 命令中使用 at isolation read uncommitted 子 句的方法解决。该方法实际上降低了 select 语句对整张表的锁级别,提高了其他用户对该表
2. 死锁排查
(1). 使用 SQL Server 的系统存储过程 sp_who 和 sp_lock,可以查看当前数据库中的锁情况;进而根据 objectID(@objID)(SQL Server 2005)/ object_name(@objID)(Sql Server 2000)可以查看哪个资源被锁, 用 dbcc ld(@blk),可以查看最后一条发生给 SQL Server 的 Sql 语句;
breakConnection)
在 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean
breakConnection)

System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject
stateObj)
在 System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler,
SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject
3、SQL Server 死锁总结 1. 死锁原理
根据操作系统中的定义:死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其 他进程所站用不会释放的资源而处于的一种永久等待状态。
死锁的四个必要条件: 互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。 请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源。 非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。 循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资 源。
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
事务(进程 ID 60)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运
行该事务。

System.Data.SqlClient.SqlConnectioption, Boolean
CREATE Table #Who(spid int, ecid int, status nvarchar(50), loginname nvarchar(50), hostname nvarchar(50), blk int, dbname nvarchar(50), cmd nvarchar(50), request_ID int);
说明:T1、T2 表示两个任务;R1 和 R2 表示两个资源;由资源指向任务的箭头(如 R1-<T1,R2-<T2) 表示该资源被改任务所持有;由任务指向资源的箭头(如 T1-<S2,T2-<S1)表示该任务正在请求对应目标资 源;
其满足上面死锁的四个必要条件: (1).互斥:资源 S1 和 S2 不能被共享,同一时间只能由一个任务使用; (2).请求与保持条件:T1 持有 S1 的同时,请求 S2;T2 持有 S2 的同时请求 S1; (3).非剥夺条件:T1 无法从 T2 上剥夺 S2,T2 也无法从 T1 上剥夺 S1; (4).循环等待条件:上图中的箭头构成环路,存在循环等待。
此句应该改为 update t_sms_send set msg_flag = -1 where id in (select top 100 id from t_sms_send with (nolock) where msg_flag=-2)
事务(进程 ID )与另一个进程已被死锁在 lock 资源上,且该事务已被选作死锁牺牲品。 请重新运行该事务 其实所有的死锁最深层的原因就是一个:资源竞争 表现一: 一个用户 A 访问表 A(锁住了表 A),然后又访问表 B 另一个用户 B 访问表 B(锁住了表 B),然后企图访问表 A 这时用户 A 由于用户 B 已经锁住表 B,它必须等待用户 B 释放表 B,才能继续,好了他老人家 就只好老老实实在这等了 同样用户 B 要等用户 A 释放表 A 才能继续这就死锁了 解决方法: 这种死锁是由于你的程序的 BUG 产生的,除了调整你的程序的逻辑别无他法 仔细分析你程序的逻辑, 1:尽量避免同时锁定两个资源 2: 必须同时锁定两个资源时,要保证在任何时刻都应该按照相同的顺序来锁定资源. 表现二: 用户 A 读一条纪录,然后修改该条纪录 这是用户 B 修改该条纪录 这里用户 A 的事务里锁的性质由共享锁企图上升到独占锁(for update),而用户 B 里的独占锁 由于 A 有共享锁存在所以必须等 A 释
放掉共享锁,而 A 由于 B 的独占锁而无法上升的独占锁也就不可能释放共享锁,于是出现 了死锁。 这种死锁比较隐蔽,但其实在稍大点的项目中经常发生。 解决方法: 让用户 A 的事务(即先读后写类型的操作),在 select 时就是用 Update lock 语法如下:
select * from table1 with(updlock) where .... ========================== 在联机事务处理(OLTP)的数据库应用系统中,多用户、多任务的并发性是系统最重要的技术 指标之一。为了提高并发性,目前大部分 RDBMS 都采用加锁技术。然而由于现实环境的复 杂性,使用加锁技术又不可避免地产生了死锁问题。因此如何合理有效地使用加锁技术,最 小化死锁是开发联机事务处理系统的关键。 死锁产生的原因 在联机事务处理系统中,造成死机主要有两方面原因。一方面,由于多用户、多任务的并发 性和事务的完整性要求,当多个事务处理对多个资源同时访问时,若双方已锁定一部分资源 但也都需要对方已锁定的资源时,无法在有限的时间内完全获得所需的资源,就会处于无限 的等待状态,从而造成其对资源需求的死锁。 另一方面,数据库本身加锁机制的实现方法不同,各数据库系统也会产生其特殊的死锁情况。 如在 Sybase SQL Server 11 中,最小锁为 2K 一页的加锁方法,而非行级锁。如果某张表的记 录数少且记录的长度较短(即记录密度高,如应用系统中的系统配置表或系统参数表就属于 此类表),被访问的频率高,就容易在该页上产生死锁。 几种死锁情况及解决方法 清算应用系统中,容易发生死锁的几种情况如下: ● 不同的存储过程、触发器、动态 SQL 语句段按照不同的顺序同时访问多张表; ● 在交换期间添加记录频繁的表,但在该表上使用了非群集索引(non‐clustered); ● 表中的记录少,且单条记录较短,被访问的频率较高; ● 整张表被访问的频率高(如代码对照表的查询等)。 以上死锁情况的对应处理方法如下: ● 在系统实现时应规定所有存储过程、触发器、动态 SQL 语句段中,对多张表的操作总是 使用同一顺序。如:有两个存储过程 proc1、proc2,都需要访问三张表 zltab、z2tab 和 z3tab, 如果 proc1 按照 zltab、z2tab 和 z3tab 的顺序进行访问,那么,proc2 也应该按照以上顺序访 问这三张表。 ● 对在交换期间添加记录频繁的表,使用群集索引(clustered),以减少多个用户添加记录到 该表的最后一页上,在表尾产生热点,造成死锁。这类表多为往来账的流水表,其特点是在 交换期间需要在表尾追加大量的记录,并且对已添加的记录不做或较少做删除操作。 ● 对单张表中记录数不太多,且在交换期间 select 或 updata 较频繁的表可使用设置每页最 大行的办法,减少数据在表中存放的密度,模拟行级锁,减少在该表上死锁情况的发生。这 类表多为信息繁杂且记录条数少的表。 如:系统配置表或系统参数表。在定义该表时添加如下语句:
stateObj)
在 System.Data.SqlClient.SqlDataReader.HasMoreRows()
在 System.Data.SqlClient.SqlDataReader.ReadInternal(Boolean setTimeout)
在 System.Data.SqlClient.SqlDataReader.Read()
在 HonryLCD.honry.lcd.LcdPatientFrm.getBed()
二、处理说明 1、查看锁状态
连上数据库后,在查询界面中按 Ctrl+2 键可以查询状态,如下:
2、事务(进程 ID 59)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲 品。请重
update t_sms_send set msg_flag = -1 where id in (select top 100 id from t_sms_send where msg_flag=-2)
事务(进程 ID 60)与另一个进程被死锁在锁资源上,并且已被选作死锁牺牲品。请重新运行 该事务。
一、问题描述
近期,由于二十多台电脑同时访问一台 SQL Server 2005 服务器,并且数据每间隔 3 分钟从 另一个 Oracle 数据库中读取数据信息供 20 多台电脑查询与显示,在信息显示时,经常报下 面的错误,导致程序出错。
对应到 SQL Server 中,当在两个或多个任务中,如果每个任务锁定了其他任务试图锁定的资源,此
相关主题