经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » MS SQL Server » 查看文章
SQL Server阻塞的检查
来源:cnblogs  作者:东山絮柳仔  时间:2019/5/9 8:45:56  对本文有异议

1. 阻塞  

除了内存、CPU、I/O这些系统资源以外,阻塞和死锁是影响数据库应用性能的另一大因素。

所谓的「阻塞」,是指当一个数据库会话中的事务,正在锁定其他会话事务想要读取或修改的资源,造成这些会话发出的请求进入等待的状态。SQL Server 默认会让被阻塞的请求无限期地一直等待,直到原来的事务释放相关的锁,或直到它超时、服务器关闭、进程被杀死。一般的系统中,偶尔有短时间的阻塞是正常且合理的;但若设计不良的程序,就可能导致长时间的阻塞,这样就不必要地锁定了资源,而且阻塞了其他会话欲读取或更新的需求。遇到这种情况,可能就需要手工排除阻塞的状态。

2.阻塞和死锁可能带来的问题

(1)并发用户少的时候,一切还都正常。但是随着并发用户的增加,性能越来越慢。

(2)应用程序运行很慢,但是SQL Server 这个CPU和磁盘利用率很低。

(3)客户端经常受到以下错误。

   Error 1222--Lock request time out period exceeded.

   Error 1205--Your transaction(process ID #XX) was deadlocked on resources with another process and has been chosen as the deadlock victim. Return your transaction.

  超时错误--Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

(4)有些查询能够进行,但是有些特定的查询或修改总是不能返回。

(5)重启SQL Server就能解决。但是有可能跑一段时间以后又会出现问题。

3.阻塞的检查

3.1 主要的系统表或函数

Sys.SysProcesses 系统表是一个很重要的系统视图,主要用来定位与解决Sql Server的阻塞和死锁。主要字段1.Spid:Sql Servr 会话ID 2.Blocked:正在阻塞求情的会话 ID。如果此列为 Null,则标识请求未被阻塞 3. Program_name:应用程序的名称,就是 连接字符串中配的 Application Name 4. Hostname:建立链接的客户端工作站的名称。

sys.dm_exec_requests、sys.dm_exec_sql_text返回指定SPIDer的 SQL 查询文本。

DBCC INPUTBUFFER 显示从客户端发送到 Microsoft SQL Server 实例的最后一个语句。

sp_lock 系统存储过程,报告有关锁的信息。

3.2 Check逻辑

对应的存储为dblockcheck(job为DB_Lockcheck),主要Check逻辑如下:

3.3 保存的数据

所收集的数据保存dblock_information中,主要包含信息如截图,定期的统计分析可获得经常被阻塞和引起阻塞SQL语句和Table,这些信息是进行数据库优化的一个角度。

  1. select top 100* from dblock_information
  2. order by TransDateTime desc

4.代码实现

4.1 Table的创建脚本

  1. CREATE TABLE [dbo].[dblock_information](
  2. [ID] [int] IDENTITY(1,1) NOT NULL,
  3. [Message] [nvarchar](300) NULL,
  4. [LockType] [char](1) NULL,
  5. [SPID1] [int] NULL,
  6. [SPID2] [int] NULL,
  7. [EventType] [nvarchar](100) NULL,
  8. [Parameters] [nvarchar](10) NULL,
  9. [EventInfo] [nvarchar](3000) NULL,
  10. [IndividualQuery] [nvarchar](1000) NULL,
  11. [TransDateTime] [datetime] NULL CONSTRAINT [DF_dblock_information_TransDateTime] DEFAULT (getdate()),
  12. [AppName] [varchar](50) NULL,
  13. [HostName] [varchar](50) NULL,
  14. CONSTRAINT [PK_dblock_information] PRIMARY KEY CLUSTERED
  15. (
  16. [ID] ASC
  17. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  18. ) ON [PRIMARY]

4.2 存储的创建脚本

  1. Create procedure [dbo].[dblockcheck]
  2. @AlarmThreshold as tinyint=10
  3. as
  4. set nocount on
  5. --------------------------------------------------------------------------------------------------------
  6. --*Program*: <dblock check for job>
  7. --*Programer*:<>
  8. --*Date*:<>
  9. --*Description*:<Query SQL Locking Process>
  10. --*Unify*:<UA>
  11. --########## Parameter Description Begin ##########
  12.  
  13. --########## Parameter Description End # ##########
  14.  
  15. --##########Update Log Begin ###################
  16. --##########Update Log End # ###################
  17. --------------------------------------------------------------------------------------------------------
  18. declare @SQL as varchar(200)
  19. declare @Subject as varchar(200)
  20. declare @Body as nvarchar(max)
  21. declare @SPName as nvarchar(max)
  22. declare @Message as nvarchar(200)
  23. declare @DBname varchar(15)
  24. declare @IP varchar(20)
  25. declare @CNT as int
  26. declare @cnt2 int
  27. declare @IndividualQuery nvarchar(1000)
  28. declare @HostName varchar(50)
  29. declare @AppName varchar(50)
  30. SET @DBname=DB_NAME()
  31. SELECT @IP='XXX.XXX.XXX.XXX'
  32. ----不手动定义IP也可通过以下函数来实现
  33. Declare @ServerIP NVARCHAR(30)='', @SERVERNAME NVARCHAR(60)=''
  34. SELECT top 1 @SERVERNAME = @@SERVERNAME ,@ServerIP=LOCAL_NET_ADDRESS
  35. FROM SYS.DM_EXEC_CONNECTIONS where LOCAL_NET_ADDRESS is not null
  36. --------
  37. begin
  38. declare @spid int,@bl int,
  39. @intTransactionCountOnEntry int,
  40. @intRowcount int,
  41. @intCountProperties int,
  42. @intCounter int
  43.  
  44. create table #tmp_lock_who (
  45. id int identity(1,1),
  46. spid smallint,
  47. bl smallint)
  48. create table #tmp_lock_information (
  49. id int identity(1,1),
  50. Message nvarchar(200),
  51. LockType char(1),
  52. SPID1 int,
  53. SPID2 int,
  54. EventType nvarchar(100),
  55. Parameters nvarchar(10),
  56. EventInfo nvarchar(max),
  57. IndividualQuery nvarchar(1000),
  58. AppName varchar(50),
  59. HostName varchar(50)
  60. )
  61. IF @@ERROR<>0 RETURN @@ERROR
  62. insert into #tmp_lock_who(spid,bl)
  63. select 0 ,blocked
  64. from (select * from master..sysprocesses where blocked>0 ) a
  65. where not exists(select * from (select * from master..sysprocesses where blocked>0 ) b
  66. where a.blocked=spid)
  67. union
  68. select spid,blocked from master..sysprocesses where blocked>0
  69. IF @@ERROR<>0 RETURN @@ERROR
  70. -- 找到临时表的记录数
  71. select @intCountProperties = Count(*),@intCounter = 1
  72. from #tmp_lock_who
  73. IF @@ERROR<>0 RETURN @@ERROR
  74. if @intCountProperties=0
  75. select N'现在没有阻塞信息!' as message
  76. -- 循环开始
  77. while @intCounter <= @intCountProperties
  78. begin
  79. -- 取第一条记录
  80. select @spid = spid,@bl = bl
  81. from #tmp_lock_who where Id = @intCounter
  82. begin
  83. SELECT @IndividualQuery= SUBSTRING (qr.text,qs.statement_start_offset/2,
  84. (CASE WHEN qs.statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX), qr.text)) * 2
  85. ELSE qs.statement_end_offset END - qs.statement_start_offset)/2)
  86. FROM SYS.DM_EXEC_REQUESTS qs OUTER APPLY SYS.DM_EXEC_SQL_TEXT(qs.sql_handle) AS qr
  87. WHERE qr.text is not null and qs.session_id=@bl
  88. select @HostName=left(HostName,50),@AppName=Left(Program_Name,50)
  89. from master..sysprocesses With(nolock) Where SPID=@bl
  90. set @SQL='DBCC INPUTBUFFER ('+cast(@bl as char(20))+')'
  91. if @spid =0
  92. begin
  93. select @Message=N'引起数据库阻塞的是: '+ CAST(@bl AS NVARCHAR(100)) + N'进程号,其执行的SQL语法如下'
  94. --set @SQL='DBCC INPUTBUFFER ('+cast(@bl as char(20))+')'
  95. insert into #tmp_lock_information(EventType,Parameters,EventInfo) exec(@sql)
  96. update #tmp_lock_information set LockType='1',SPID1=@bl,SPID2=@bl,IndividualQuery=@IndividualQuery,[Message]=@Message,AppName=@APPName,HostName=@HostName where [Message] is null
  97. end
  98. else
  99. begin
  100. select @Message=N'进程号SPID:'+ CAST(@spid AS NVARCHAR(100))+ N'' + N'进程号SPID:'+ CAST(@bl AS NVARCHAR(10)) +N'阻塞,其当前进程执行的SQL语法如下'
  101. insert into #tmp_lock_information(EventType,Parameters,EventInfo) exec(@sql)
  102. update #tmp_lock_information set LockType='2', SPID1=@spid,SPID2=@bl,IndividualQuery=@IndividualQuery,[Message]=@Message,AppName=@APPName,HostName=@HostName where [Message] is null
  103. end
  104. end
  105. -- 循环指针下移
  106. set @intCounter = @intCounter + 1
  107. end
  108. drop table #tmp_lock_who
  109. if exists(select 0 from #tmp_lock_information)
  110. Begin
  111.  
  112. Insert into dblock_information(Message,LockType,SPID1,SPID2,EventType,Parameters,EventInfo,IndividualQuery,AppName,HostName)
  113. Select [Message],LockType,SPID1,SPID2,EventType,Parameters,Substring(EventInfo,1,500),IndividualQuery,AppName,HostName from #tmp_lock_information
  114. End
  115.  
  116. drop table #tmp_lock_information
  117. return 0
  118. end

 

原文链接:http://www.cnblogs.com/xuliuzai/p/10832615.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号