sql死锁查询
1. 如何查看sql Server 2008的死锁
在SQL Server 2008数据库中,查看死锁可以用存储过程来实现,本文我们主要就介绍了SQL Server 2008查看死锁的存储过程的代码示例,希望能够对您有所帮助。
代码示例如下:
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[sp_who_lock]') and OBJECTPROPERTY(id, N'IsProcere') = 1) drop procere [dbo].[sp_who_lock] GO use master go create procere sp_who_lock as begin declare @spid int,@bl int, @intTransactionCountOnEntry int, @intRowcount int, @intCountProperties int, @intCounter int create table #tmp_lock_who ( id int identity(1,1), spid smallint, bl smallint) IF @@ERROR<>0 RETURN @@ERROR insert into #tmp_lock_who(spid,bl) select 0 ,blocked from (select * from sysprocesses where blocked>0 ) a where not exists(select * from (select * from sysprocesses where blocked>0 ) b where a.blocked=spid) union select spid,blocked from sysprocesses where blocked>0 IF @@ERROR<>0 RETURN @@ERROR -- 找到临时表的记录数 select @intCountProperties = Count(*),@intCounter = 1 from #tmp_lock_who IF @@ERROR<>0 RETURN @@ERROR if @intCountProperties=0 select '现在没有阻塞和死锁信息' as message -- 循环开始 while @intCounter <= @intCountProperties begin -- 取第一条记录 select @spidspid = spid,@blbl = bl from #tmp_lock_who where Id = @intCounter begin if @spid =0 select '引起数据库死锁的是: '+ CAST(@bl AS VARCHAR(10)) + '进程号,其执行的SQL语法如下' else select '进程号SPID:'+ CAST(@spid AS VARCHAR(10))+ '被' + '进程号SPID:'+ CAST(@bl AS VARCHAR(10)) +'阻塞,其当前进程执行的SQL语法如下' DBCC INPUTBUFFER (@bl ) end -- 循环指针下移 set @intCounter = @intCounter + 1 end drop table #tmp_lock_who return 0 end
以上就是SQL Server 2008查看死锁的存储过程的代码示例的全部内容,本文我们就介绍到这里了,希望本次的介绍能够对您有所收获!
2. 怎么查看 sql server 2008 死锁日志
1.查询分析器执行 sp_lock 查看
2.右键服务器-选择“活动和监视器”,查看进程选项。注意“任务状态”字段。
3.右键服务名称-选择报表-标准报表-活动-所有正在阻塞的事务。祝你愉快,满意请采纳哦
3. 如何查看SQL死锁
其实所有的死锁最深层的原因就是一个:资源竞争
表现一:
一个用户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 ....
4. sqlserver怎么用sql查看具体那个表被锁住了
详细步骤如下:
1、点击【新建查询】按钮,打开SQL命令编辑框,对数据库表的操作以及维护都可以通过编辑SQL命令实现。
3、创建数据表的源代码如下:
use test go
if exists(select name from sys.tables where name='Student')
drop table Student go
create table Student
(sname nchar(10) primary key,
sex nchar(2) not null,
bir datetime)
5. 怎样查询引起死锁的sql语句
elect 0 ,blocked
from (select * from sysprocesses where blocked>0 ) a
where not exists(select * from (select * from sysprocesses where blocked>0 ) b
where a.blocked=spid)
union select spid,blocked from sysprocesses where blocked>0
OPEN s_cur
FETCH NEXT FROM s_cur INTO @spid,@bl
WHILE @@FETCH_STATUS = 0
begin
if @spid =0
select ' 引起数梁尘据库死锁的是: '+ CAST(@bl AS VARCHAR(10)) + ' 进程号, 其执行的SQL 语法如下'
else
select ' 进程号塌型SPID :'+ CAST(@spid AS VARCHAR(10))+ ' 被橡衫禅' + ' 进程号SPID :'+ CAST(@bl AS VARCHAR(10)) +' 阻塞, 其当前进程执行的SQL 语法如下'
DBCC INPUTBUFFER (@bl )
6. SQLServer死锁的解除方法
SQL Server死锁使我们经差键常遇到的问题 下面就为您介绍如何查询SQL Server死喊庆晌锁 希望对您学习SQL Server死锁方面能有所帮郑锋助
SQL Server死锁的查询方法
exec master dbo p_lockinfo 显示死锁的进程 不显示正常的进程
exec master dbo p_lockinfo 杀死死锁的进程 不显示正常的进程
SQL Server死锁的解除方法
Create proc p_lockinfo
@kill_lock_spid bit= 是否杀掉死锁的进程 杀掉 仅显示
@show_spid_if_nolock bit= 如果没有死锁的进程 是否显示正常进程信息 显示 不显示
as
declare @count int @s nvarchar( ) @i int
select id=identity(int ) 标志
进程ID=spid 线程ID=kpid 块进程ID=blocked 数据库ID=dbid
数据库名=db_name(dbid) 用户ID=uid 用户名=loginame 累计CPU时间=cpu
登陆时间=login_time 打开事务数=open_tran 进程状态=status
工作站名=hostname 应用程序名=program_name 工作站进程ID=hostprocess
域名=nt_domain 网卡地址=net_address
into #t from(
select 标志= 死锁的进程
spid kpid a blocked dbid uid loginame cpu login_time open_tran
status hostname program_name hostprocess nt_domain net_address
s =a spid s =
from mastersysprocesses a join (
select blocked from mastersysprocesses group by blocked
)b on a spid=b blocked where a blocked=
union all
select |_牺牲品_>
spid kpid blocked dbid uid loginame cpu login_time open_tran
status hostname program_name hostprocess nt_domain net_address
s =blocked s =
from mastersysprocesses a where blocked<>
)a order by s s
select @count=@@rowcount @i=
if @count= and @show_spid_if_nolock=
begin
insert #t
select 标志= 正常的进程
spid kpid blocked dbid db_name(dbid) uid loginame cpu login_time
open_tran status hostname program_name hostprocess nt_domain net_address
from mastersysprocesses
set @count=@@rowcount
end
if @count>
begin
create table #t (id int identity( ) a nvarchar( ) b Int EventInfo nvarchar( ))
if @kill_lock_spid=
begin
declare @spid varchar( ) @标志 varchar( )
while @i<=@count
begin
select @spid=进程ID @标志=标志 from #t whereid=@i
insert #t exec( dbcc inputbuffer( +@spid+ ) )
if @标志= 死锁的进程 exec( kill +@spid)
set @i=@i+
end
end
else
while @i<=@count
begin
select @s= dbcc inputbuffer( +cast(进程ID as varchar)+ ) from #t whereid=@i
insert #t exec(@s)
set @i=@i+
end
select a * 进程的SQL语句=b EventInfo
from #t a join #t b on a id=b id
lishixin/Article/program/SQLServer/201311/22183
7. 如何查看SQL表死锁
SELECT SPID=p.spid,
DBName = convert(CHAR(20),d.name),
ProgramName = program_name,
LoginName = convert(CHAR(20),l.name),
HostName = convert(CHAR(20),hostname),
Status = p.status,
BlockedBy = p.blocked,
LoginTime = login_time,
QUERY = CAST(t.TEXT AS VARCHAR(MAX))
FROM MASTER.dbo.sysprocesses p
INNER JOIN MASTER.dbo.sysdatabases d
ON p.dbid = d.dbid
INNER JOIN MASTER.dbo.syslogins l
ON p.sid = l.sid
CROSS APPLY sys.dm_exec_sql_text(sql_handle) t
WHERE p.blocked = 0
AND EXISTS (SELECT 1
FROM MASTER.dbo.sysprocesses p1
WHERE p1.blocked = p.spid)
SELECT SPID=p.spid,
DBName = convert(CHAR(20),d.name),
ProgramName = program_name,
LoginName = convert(CHAR(20),l.name),
HostName = convert(CHAR(20),hostname),
Status = p.status,
BlockedBy = p.blocked,
LoginTime = login_time,
QUERY = CAST(t.TEXT AS VARCHAR(MAX))
FROM MASTER.dbo.sysprocesses p
INNER JOIN MASTER.dbo.sysdatabases d
ON p.dbid = d.dbid
INNER JOIN MASTER.dbo.syslogins l
ON p.sid = l.sid
CROSS APPLY sys.dm_exec_sql_text(sql_handle) t
WHERE p.blocked = 0
AND EXISTS (SELECT 1
FROM MASTER.dbo.sysprocesses p1
WHERE p1.blocked = p.spid)
用这个查询两次,如果两次都有某个语句就是了,可以用kill结束它
8. 如何查看SQL Server 2008的死锁
为了查看死锁信息,数据库引擎提供了监视工具,分别为两个跟踪标志以及
SQL
Server
Profiler中的死锁图形事件。
跟踪标志
1204
和跟踪标志
1222
发生死锁时,跟踪标志
1204
和跟踪标志
1222
会返回在
SQL
Server
错误日志中捕获的信息。跟踪标志
1204
会报告由死锁所涉及的每个节点设置格式的死锁信息。跟踪标志
1222
会设置死锁信息的格式,顺序为先按进程,然后按资源。可以同时启用这两个跟踪标志,以获取同一个死锁事件的两种表示形式。
SQL
Server
Profiler
中的
TraceEvent
Class:
LocksEvent
Name:
Deadlock
Graph
提供
一个XML
图表.,你可以从中看出发生了什么。
9. mysql 查看死锁
第一步,查出已锁的进程
查侍者看正在锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
``
查看等待锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
``
INNODB_TRX表主要是包含了正在InnoDB引擎中执行的所有事务的信息,包括贺谈散waiting for a lock和禅氏running的事务
select * from information_schema.innodb_trx
``
第二步,kill进程
show engin innodb status; //最后一次死锁信息及sql
show open tables where in_use > 0 //查看锁表
10. 如何处理SQL Server死锁问题
死锁,简而言之,两个或者多个trans,同时请求对方正在请求的某个对象,导致双方互相等待。简单的例子如下:x0dx0a trans1 trans2x0dx0a ------------------------------------------------------------------------x0dx0a 1.IDBConnection.BeginTransaction 1.IDBConnection.BeginTransactionx0dx0a 2.update table A 2.update table Bx0dx0a 3.update table B 3.update table Ax0dx0a 4.IDBConnection.Commit 4.IDBConnection.Commit x0dx0a 那么,很容易看到,如果trans1和trans2,分别到达了step3,那么trans1会请求对于B的X锁,trans2会请求对于A的X锁,而二者的锁在step2上已经被对方分别持有了。由于得不到锁,后面的Commit无法执行,这样双方开始死锁。x0dx0a 好,我们看一个简单的例子,来解释一下,应该如何解决死锁问题。x0dx0a -- Batch #1x0dx0a CREATE DATABASE deadlocktestx0dx0a GOx0dx0a USE deadlocktestx0dx0a SET NOCOUNT ONx0dx0a DBCC TRACEON (1222, -1)x0dx0a -- 在SQL2005中,增加了一个新的dbcc参数,就是1222,原来在2000下,我们知道,可以执行dbcc x0dx0a --traceon(1204,3605,-1)看到所有的死锁信息。SqlServer 2005中,对于1204进行了增强,这就是1222。x0dx0a GO x0dx0a x0dx0a IF OBJECT_ID ('t1') IS NOT NULL DROP TABLE t1x0dx0a IF OBJECT_ID ('p1') IS NOT NULL DROP PROC p1x0dx0a IF OBJECT_ID ('p2') IS NOT NULL DROP PROC p2x0dx0a GOx0dx0a CREATE TABLE t1 (c1 int, c2 int, c3 int, c4 char(5000)) x0dx0a GOx0dx0a DECLARE @x intx0dx0a SET @x = 1x0dx0a WHILE (@x <= 1000) BEGINx0dx0a INSERT INTO t1 VALUES (@x*2, @x*2, @x*2, @x*2)x0dx0a SET @x = @x + 1x0dx0a ENDx0dx0a GOx0dx0a CREATE CLUSTERED INDEX cidx ON t1 (c1)x0dx0a CREATE NONCLUSTERED INDEX idx1 ON t1 (c2)x0dx0a GOx0dx0a CREATE PROC p1 @p1 int AS SELECT c2, c3 FROM t1 WHERE c2 BETWEEN @p1 AND @p1+1x0dx0a GOx0dx0a CREATE PROC p2 @p1 int ASx0dx0a UPDATE t1 SET c2 = c2+1 WHERE c1 = @p1x0dx0a UPDATE t1 SET c2 = c2-1 WHERE c1 = @p1x0dx0a GOx0dx0a 上述sql创建一个deadlock的示范数据库,插入了1000条数据,并在表t1上建立了c1列的聚集索引,和c2列的非聚集索引。另外创建了两个sp,分别是从t1中select数据和update数据。 x0dx0a 好,打开一个新的查询窗口,我们开始执行下面的query:x0dx0a -- Batch #2x0dx0a USE deadlocktestx0dx0a SET NOCOUNT ONx0dx0a WHILE (1=1) EXEC p2 4x0dx0a GOx0dx0a 开始执行后,然后我们打开第三个查询窗口,执行下面的query:x0dx0a -- Batch #3x0dx0a USE deadlocktestx0dx0a SET NOCOUNT ONx0dx0a CREATE TABLE #t1 (c2 int, c3 int)x0dx0a GOx0dx0a WHILE (1=1) BEGINx0dx0a INSERT INTO #t1 EXEC p1 4x0dx0a TRUNCATE TABLE #t1x0dx0a ENDx0dx0a GOx0dx0a 开始执行,哈哈,很快,我们看到了这样的错误信息:x0dx0a Msg 1205, Level 13, State 51, Procere p1, Line 4x0dx0a Transaction (Process ID 54) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.x0dx0a spid54发现了死锁。 x0dx0a 那么,我们该如何解决它?x0dx0a 在SqlServer 2005中,我们可以这么做:x0dx0a 1.在trans3的窗口中,选择EXEC p1 4,然后right click,看到了菜单了吗?选择Analyse Query in Database Engine Tuning Advisor。x0dx0a 2.注意右面的窗口中,wordload有三个选择:负载文件、表、查询语句,因为我们选择了查询语句的方式,所以就不需要修改这个radio option了。x0dx0a 3.点左上角的Start Analysis按钮x0dx0a 4.抽根烟,回来后看结果吧!出现了一个分析结果窗口,其中,在Index Recommendations中,我们发现了一条信息:大意是,在表t1上增加一个非聚集索引索引:t2+t1。x0dx0a 5.在当前窗口的上方菜单上,选择Action菜单,选择Apply Recommendations,系统会自动创建这个索引。x0dx0a 重新运行batch #3,呵呵,死锁没有了。x0dx0a 这种方式,我们可以解决大部分的Sql Server死锁问题。那么,发生这个死锁的根本原因是什么呢?为什么增加一个non clustered index,问题就解决了呢? 这次,我们分析一下,为什么会死锁呢?再回顾一下两个sp的写法:x0dx0a CREATE PROC p1 @p1 int AS x0dx0a SELECT c2, c3 FROM t1 WHERE c2 BETWEEN @p1 AND @p1+1 x0dx0a GOx0dx0a CREATE PROC p2 @p1 int ASx0dx0a UPDATE t1 SET c2 = c2+1 WHERE c1 = @p1x0dx0a UPDATE t1 SET c2 = c2-1 WHERE c1 = @p1x0dx0a GOx0dx0a 很奇怪吧!p1没有insert,没有delete,没有update,只是一个select,p2才是update。这个和我们前面说过的,trans1里面updata A,update B;trans2里面upate B,update A,根本不贴边啊!x0dx0a 那么,什么导致了死锁?x0dx0a 需要从事件日志中,看sql的死锁信息:x0dx0a Spid X is running this query (line 2 of proc [p1], inputbuffer “? EXEC p1 4 ?”): x0dx0a SELECT c2, c3 FROM t1 WHERE c2 BETWEEN @p1 AND @p1+1x0dx0a Spid Y is running this query (line 2 of proc [p2], inputbuffer “EXEC p2 4”): x0dx0a UPDATE t1 SET c2 = c2+1 WHERE c1 = @p1x0dx0a x0dx0a The SELECT is waiting for a Shared KEY lock on index t1.cidx. The UPDATE holds a conflicting X lock. x0dx0a The UPDATE is waiting for an eXclusive KEY lock on index t1.idx1. The SELECT holds a conflicting S lock.x0dx0a 首先,我们看看p1的执行计划。怎么看呢?可以执行set statistics profile on,这句就可以了。下面是p1的执行计划x0dx0a SELECT c2, c3 FROM t1 WHERE c2 BETWEEN @p1 AND @p1+1x0dx0a |--Nested Loops(Inner Join, OUTER REFERENCES:([Uniq1002], [t1].[c1]))x0dx0a |--Index Seek(OBJECT:([t1].[idx1]), SEEK:([t1].[c2] >= [@p1] AND [t1].[c2] <= [@p1]+(1)) ORDERED FORWARD)x0dx0a |--Clustered Index Seek(OBJECT:([t1].[cidx]), SEEK:([t1].[c1]=[t1].[c1] AND [Uniq1002]=[Uniq1002]) LOOKUP ORDERED FORWARD)x0dx0a 我们看到了一个nested loops,第一行,利用索引t1.c2来进行seek,seek出来的那个rowid,在第二行中,用来通过聚集索引来查找整行的数据。这是什么?就是bookmark lookup啊!为什么?因为我们需要的c2、c3不能完全的被索引t1.c1带出来,所以需要书签查找。 x0dx0a 好,我们接着看p2的执行计划。x0dx0a UPDATE t1 SET c2 = c2+1 WHERE c1 = @p1x0dx0a |--Clustered Index Update(OBJECT:([t1].[cidx]), OBJECT:([t1].[idx1]), SET:([t1].[c2] = [Expr1004]))x0dx0a |--Compute Scalar(DEFINE:([Expr1013]=[Expr1013]))x0dx0a |--Compute Scalar(DEFINE:([Expr1004]=[t1].[c2]+(1), [Expr1013]=CASE WHEN CASE WHEN ...x0dx0a |--Top(ROWCOUNT est 0)x0dx0a |--Clustered Index Seek(OBJECT:([t1].[cidx]), SEEK:([t1].[c1]=[@p1]) ORDERED FORWARD) x0dx0a 通过聚集索引的seek找到了一行,然后开始更新。这里注意的是,update的时候,它会申请一个针对clustered index的X锁的。x0dx0a 实际上到这里,我们就明白了为什么update会对select产生死锁。update的时候,会申请一个针对clustered index的X锁,这样就阻塞住了(注意,不是死锁!)select里面最后的那个clustered index seek。死锁的另一半在哪里呢?注意我们的select语句,c2存在于索引idx1中,c1是一个聚集索引cidx。问题就在这里!我们在p2中更新了c2这个值,所以sqlserver会自动更新包含c2列的非聚集索引:idx1。而idx1在哪里?就在我们刚才的select语句中。而对这个索引列的更改,意味着索引集合的某个行或者某些行,需要重新排列,而重新排列,需要一个X锁。x0dx0a SO???,问题就这样被发现了。x0dx0a 总结一下,就是说,某个query使用非聚集索引来select数据,那么它会在非聚集索引上持有一个S锁。当有一些select的列不在该索引上,它需要根据rowid找到对应的聚集索引的那行,然后找到其他数据。而此时,第二个的查询中,update正在聚集索引上忙乎:定位、加锁、修改等。但因为正在修改的某个列,是另外一个非聚集索引的某个列,所以此时,它需要同时更改那个非聚集索引的信息,这就需要在那个非聚集索引上,加第二个X锁。select开始等待update的X锁,update开始等待select的S锁,死锁,就这样发生鸟。 x0dx0a 那么,为什么我们增加了一个非聚集索引,死锁就消失鸟?我们看一下,按照上文中自动增加的索引之后的执行计划:x0dx0a SELECT c2, c3 FROM t1 WHERE c2 BETWEEN @p1 AND @p1+1x0dx0a |--Index Seek(OBJECT:([deadlocktest].[dbo].[t1].[_dta_index_t1_7_2073058421__K2_K1_3]), SEEK:([deadlocktest].[dbo].[t1].[c2] >= [@p1] AND [deadlocktest].[dbo].[t1].[c2] <= [@p1]+(1)) ORDERED FORWARD)x0dx0a 哦,对于clustered index的需求没有了,因为增加的覆盖索引已经足够把所有的信息都select出来。就这么简单。x0dx0a 实际上,在sqlserver 2005中,如果用profiler来抓eventid:1222,那么会出现一个死锁的图,很直观的说。x0dx0a 下面的方法,有助于将死锁减至最少(详细情况,请看SQLServer联机帮助,搜索:将死锁减至最少即可。x0dx0a按同一顺序访问对象。 x0dx0a避免事务中的用户交互。 x0dx0a保持事务简短并处于一个批处理中。 x0dx0a使用较低的隔离级别。 x0dx0a使用基于行版本控制的隔离级别。 x0dx0a将 READ_COMMITTED_SNAPSHOT 数据库选项设置为 ON,使得已提交读事务使用行版本控制。 x0dx0a使用快照隔离。x0dx0a使用绑定连接。