热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

sql2005为什么用存储过程p_lockinfo得到死锁进程的sql不准确

得到死锁进程的sql有时不对,甚至加nolock了也死锁,select*fromtwith(nolock)。用的论坛里找的p_lockinfo改了下把结果记录到表z_sql里了CREA
得到死锁进程的sql有时不对,甚至加nolock 了也死锁,select * from t with(nolock) 。用的论坛里找的p_lockinfo 改了下把结果记录到表z_sql里了
CREATE TABLE [dbo].[z_sql](
[zid] [bigint] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
[rq] [datetime] NULL CONSTRAINT [DF_z_sql_rq]  DEFAULT (getdate()),
[id] [int] NOT NULL,
[标志] [varchar](50) NOT NULL,
[进程ID] [int] NOT NULL,
[线程ID] [int] NOT NULL,
[块进程ID] [int] NOT NULL,
[数据库ID] [int] NOT NULL,
[数据库名] [varchar](50) NULL,
[用户ID] [int] NOT NULL,
[用户名] [varchar](50) NOT NULL,
[累计CPU时间] [int] NOT NULL,
[登陆时间] [datetime] NOT NULL,
[打开事务数] [int] NOT NULL,
[进程状态] [varchar](50) NOT NULL,
[工作站名] [varchar](255) NOT NULL,
[应用程序名] [varchar](255) NOT NULL,
[工作站进程ID] [varchar](20) NOT NULL,
[域名] [varchar](255) NOT NULL,
[网卡地址] [varchar](50) NOT NULL,
[进程的SQL语句] [text] NULL,
 CONSTRAINT [PK_z_sql] PRIMARY KEY CLUSTERED 
(
[zid] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

go
USE [master]
GO
/****** 对象:  StoredProcedure [dbo].[p_lockinfo]    脚本日期: 12/16/2010 08:49:14 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
create proc [dbo].[p_lockinfo]
@kill_lock_spid bit=1,  --是否杀掉死锁的进程,1 杀掉, 0 仅显示
@show_spid_if_nolock bit=1 --如果没有死锁的进程,是否显示正常进程信息,1 显示,0 不显示
as
declare @count int,@s nvarchar(1000),@i int

select id=identity(int,1,1),标志,
 进程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,
  s1=a.spid,s2=0
 from master..sysprocesses a join (
  select blocked from master..sysprocesses group by blocked
  )b on a.spid=b.blocked where a.blocked=0
 union all
 select '|_牺牲品_>',
  spid,kpid,blocked,dbid,uid,loginame,cpu,login_time,open_tran,
  status,hostname,program_name,hostprocess,nt_domain,net_address,
  s1=blocked,s2=1
 from master..sysprocesses a where blocked<>0
)a order by s1,s2

select @count=@@rowcount,@i=1

if @count=0 and @show_spid_if_nolock=1
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 master..sysprocesses
 set @count=@@rowcount
end

if @count>0
begin
 create table #t1(id int identity(1,1),a varchar(8000),b Int null,EventInfo varchar(8000) null)
 if @kill_lock_spid=1
 begin
  declare @spid varchar(10),@标志 varchar(10)
  while @i<=@count
  begin
   select @spid=进程ID,@标志=标志 from #t where id=@i
   insert #t1 exec('dbcc inputbuffer('+@spid+')')
   if @标志='死锁的进程' exec('kill '+@spid)
   set @i=@i+1
  end
 end
 else
  while @i<=@count
  begin
   select @s='dbcc inputbuffer('+cast(进程ID as varchar)+')' from #t where id=@i
   insert #t1 exec(@s)
   set @i=@i+1
  end
insert z_sql
(id, 标志, 进程ID, 线程ID, 块进程ID, 数据库ID, 数据库名, 用户ID, 用户名, 累计CPU时间, 登陆时间, 打开事务数, 进程状态, 工作站名, 应用程序名, 工作站进程ID, 域名, 网卡地址, 进程的SQL语句)
 select a.*,进程的SQL语句=b.EventInfo 
 from #t a join #t1 b on a.id=b.id
select * from z_sql
end

12 个解决方案

#1


该回复于2010-12-16 13:31:55被版主删除

#2


参考:

/*--处理死锁

 查看当前进程,或死锁进程,并能自动杀掉死进程

 因为是针对死的,所以如果有死锁进程,只能查看死锁进程
 当然,你可以通过参数控制,不管有没有死锁,都只查看死锁进程

--邹建 2004.4--*/

/*--调用示例

 exec p_lockinfo
--*/
create proc p_lockinfo
@kill_lock_spid bit=1,  --是否杀掉死锁的进程,1 杀掉, 0 仅显示
@show_spid_if_nolock bit=1 --如果没有死锁的进程,是否显示正常进程信息,1 显示,0 不显示
as
declare @count int,@s nvarchar(1000),@i int
select id=identity(int,1,1),标志,
 进程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,
  s1=a.spid,s2=0
 from master..sysprocesses a join (
  select blocked from master..sysprocesses group by blocked
  )b on a.spid=b.blocked where a.blocked=0
 union all
 select '|_牺牲品_>',
  spid,kpid,blocked,dbid,uid,loginame,cpu,login_time,open_tran,
  status,hostname,program_name,hostprocess,nt_domain,net_address,
  s1=blocked,s2=1
 from master..sysprocesses a where blocked<>0
)a order by s1,s2

select @count=@@rowcount,@i=1

if @count=0 and @show_spid_if_nolock=1
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 master..sysprocesses
 set @count=@@rowcount
end

if @count>0
begin
 create table #t1(id int identity(1,1),a nvarchar(30),b Int,EventInfo nvarchar(255))
 if @kill_lock_spid=1
 begin
  declare @spid varchar(10),@标志 varchar(10)
  while @i<=@count
  begin
   select @spid=进程ID,@标志=标志 from #t where id=@i
   insert #t1 exec('dbcc inputbuffer('+@spid+')')
   if @标志='死锁的进程' exec('kill '+@spid)
   set @i=@i+1
  end
 end
 else
  while @i<=@count
  begin
   select @s='dbcc inputbuffer('+cast(进程ID as varchar)+')' from #t where id=@i
   insert #t1 exec(@s)
   set @i=@i+1
  end
 select a.*,进程的SQL语句=b.EventInfo
 from #t a join #t1 b on a.id=b.id
end
go

#3


嘿嘿 好像都一样呀 我用下来感觉这个存储过程没问题呀 关注一下 收藏

#4


引用 3 楼 billpu 的回复:
嘿嘿 好像都一样呀 我用下来感觉这个存储过程没问题呀 关注一下 收藏

我就是修改用的论坛里找的p_lockinfo ,改了下把结果记录到表z_sql里了
但有死锁时,调用p_lockinfo ,返回得到死锁进程的sql 有时是select * from t with(nolock)  这样的也会死锁?!

#5


其它查询如与T表关联的,如update B set col=11 from B inner join T on B.id=T.id 把T表占用了.也有可能使用t表,占用了T表资源!

#6


我仔细看了一下,这个过程的描述是不准确的。

这个过程检测的并不是死锁,而是阻塞;而阻塞并不一定会形成死锁。

sysprocesses是2000下的系统表,2005以后不建议再用(可用动态管理视图代替)。检测死锁是一个递归的过程,首先查询被阻塞的进程和被阻塞的资源,再查阻塞的进程和及其锁定的资源,如果彼此互相锁定且互相请求才构成死锁。再说,这个工作事实上也是没有必要的,因为SQL会自动检测死锁,并牺牲掉一个回滚消耗少的进程。



#7


感谢coleling ,能提供个 可用动态管理视图 的例子吗?

#8


引用 7 楼 zjl8008 的回复:
感谢coleling ,能提供个 可用动态管理视图 的例子吗?


请稍等,我写个2005版的出来。

至于出现select * from t with(nolock)的问题,因为单独这个语句不受其他进程阻塞,也不会阻塞别的进程,按理说,是不应该出现。 我估计可能是最后的dbcc inputbuffer语句出的问题,因为该语句返回的是最后一条语句,在繁忙的系统中,有可能最后的语句已不是阻塞的语句。

#9


恩最后出现
select * from t with(nolock)的问题
是这样的

当进程A 锁定一个表 T1或T1的某一行,且未做完整提交的时候,其他进程想对T1或T1的特定行进行提交,就会发生阻塞
但注意,这个时候,A进程是依然可以继续向下进行运行的,只是其他的进程会被阻塞,等待A进程的完整提交而已
而使用你的查询语句,,,死锁的进程  将会返回的是A进程的spid 
你使用后dbcc inputbuffer(A进程SPID)
返回的是未被提交的A进程正在运行的最后一个SQL语句而已,,,也就是说即使是最后运行的是select 1
dbcc inputbuffer返回的也是它

也就是说你真想查找发生阻塞的语句应该获取的是,,,你使用的查询语句那个 |_牺牲品_>  返回的进程SPID
使用它,dbcc inputbuffer返回的才是其他进程被阻塞的语句

#10


引用 7 楼 zjl8008 的回复:
感谢coleling ,能提供个 可用动态管理视图 的例子吗?


我写了2005版的,见链接: http://blog.csdn.net/coleling/archive/2010/12/17/6081911.aspx

楼主,可以结贴了。

#11


这个问题一定要顶顶~~

#12


该回复于2010-12-20 14:54:45被版主删除

推荐阅读
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • ALTERTABLE通过更改、添加、除去列和约束,或者通过启用或禁用约束和触发器来更改表的定义。语法ALTERTABLEtable{[ALTERCOLUMNcolu ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文介绍了OpenStack的逻辑概念以及其构成简介,包括了软件开源项目、基础设施资源管理平台、三大核心组件等内容。同时还介绍了Horizon(UI模块)等相关信息。 ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 本文介绍了游标的使用方法,并以一个水果供应商数据库为例进行了说明。首先创建了一个名为fruits的表,包含了水果的id、供应商id、名称和价格等字段。然后使用游标查询了水果的名称和价格,并将结果输出。最后对游标进行了关闭操作。通过本文可以了解到游标在数据库操作中的应用。 ... [详细]
  • Windows7 64位系统安装PLSQL Developer的步骤和注意事项
    本文介绍了在Windows7 64位系统上安装PLSQL Developer的步骤和注意事项。首先下载并安装PLSQL Developer,注意不要安装在默认目录下。然后下载Windows 32位的oracle instant client,并解压到指定路径。最后,按照自己的喜好对解压后的文件进行命名和压缩。 ... [详细]
  • iOS Swift中如何实现自动登录?
    本文介绍了在iOS Swift中如何实现自动登录的方法,包括使用故事板、SWRevealViewController等技术,以及解决用户注销后重新登录自动跳转到主页的问题。 ... [详细]
  • RouterOS 5.16软路由安装图解教程
    本文介绍了如何安装RouterOS 5.16软路由系统,包括系统要求、安装步骤和登录方式。同时提供了详细的图解教程,方便读者进行操作。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • MySQL语句大全:创建、授权、查询、修改等【MySQL】的使用方法详解
    本文详细介绍了MySQL语句的使用方法,包括创建用户、授权、查询、修改等操作。通过连接MySQL数据库,可以使用命令创建用户,并指定该用户在哪个主机上可以登录。同时,还可以设置用户的登录密码。通过本文,您可以全面了解MySQL语句的使用方法。 ... [详细]
author-avatar
最棒的aaaaaaaaa2_531
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有