又是很久没记录工作点滴了,年后就忙着找新东家了,总算尘埃落定。不料,刚交接出去的系统就出问题了,系统老是超时。两天前看测试环境报错还没在意,因为什么代码也没改而且正式系统上也没问题,再加上公司权限系统切换有问题,大家什么异常第一个就想到权限系统。今天发现正式库上也报错了,一直报超时。于是查问题,最终结果是交接的人新加了个功能,代码中人为照成锁等待超时(在函数中前面加事务,后面没加事务,后面没加事务的等待锁释放,而事务等待执行完提交,于是造成等待超时)。
错误抽象出来如下:
- public static void Test()
- {
- using (SqlConnection myConnection = DBHelper.MyConnection)
- {
- myConnection.Open();
- SqlTransaction _varTrans = myConnection.BeginTransaction();
- try
- {
- InsertA(_varTrans);
- UpdateA(_varTrans);
- SelectA();
- _varTrans.Commit();
- }
- catch (Exception ex)
- {
- _varTrans.Rollback();
- Console.WriteLine(ex.ToString());
- }
- }
- }
查询方法:每次一卡,首先看所有的锁:exec sp_lock,查看ObjId不为0的,根据dbcc inputbuffer(spid)--spid为所有锁中的spid字段,看到执行的SQL语句为EventInfo字段,找到相应的代码。到代码中一找,原来刚接手项目的哥们新加了一个功能,断点调试,发现运行到后面的无事务查询卡住了,导致逻辑死锁,卡住的这段时间到数据库执行查询也是超时,遂以为这就是数据库的死锁。查看相关的资料发现,这种只是逻辑等待超时。
问题是解决了,然后就想可不可以用with(nolock)或者是with(readpast)的,经过业务考虑不适合;
进一步思考哪些情况会导致锁表等待,经过调查,个人从表象认为插入操作时锁主键索引,更新时锁定行,删除时锁主键索引。(具体测试代码见源码)
查询数据库锁表的语句如下:
- --查看所有锁表的语句
- use master;
- go
- if not exists(select * from sysobjects where name = '#LockDetails' and xtype='U')
- begin
- CREATE Table #LockDetails
- (
- [EventType] varchar(2000),
- [Parameters] int,
- EventInfo nvarchar(2000)
- );
- end
- go
- DECLARE crsr Cursor FOR
- SELECT spid blk FROM (
- select distinct resource_database_id dbid,
- resource_associated_entity_id objid,
- request_mode lockmode,
- request_session_id spid,
- b.name from master.sys.dm_tran_locks a
- left join master.sys.sysdatabases b on a.resource_database_id=b.dbid
- where resource_associated_entity_id<>0
- ) a;
- DECLARE @blk int;
- --游标开始
- open crsr;
- FETCH NEXT FROM crsr INTO @blk;
- WHILE (@@FETCH_STATUS=0)
- BEGIN;
- INSERT INTO #LockDetails exec('dbcc inputbuffer('+@blk+')')
- FETCH NEXT FROM crsr INTO @blk;
- END;
- close crsr;
- DEALLOCATE crsr;
- --游标结束
- select distinct * from #LockDetails;
- DROP Table #LockDetails;
参考:
SQL Server死锁总结 :http://www.cnblogs.com/happyhippy/archive/2008/11/14/1333922.htmlmsdn的sp_lock :http://msdn.microsoft.com/zh-cn/library/ms187749.aspx
msdn的sys.dm_tran_locks :http://msdn.microsoft.com/zh-cn/library/ms190345.aspx
msdn的DBCC INPUTBUFFER :http://msdn.microsoft.com/zh-cn/library/ms187730(v=SQL.105).aspx