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,这些信息是进行数据库优化的一个角度。

select top 100* from dblock_information
order by TransDateTime desc

4.代码实现

4.1 Table的创建脚本

CREATE TABLE [dbo].[dblock_information](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Message] [nvarchar](300) NULL,
[LockType] [char](1) NULL,
[SPID1] [int] NULL,
[SPID2] [int] NULL,
[EventType] [nvarchar](100) NULL,
[Parameters] [nvarchar](10) NULL,
[EventInfo] [nvarchar](3000) NULL,
[IndividualQuery] [nvarchar](1000) NULL,
[TransDateTime] [datetime] NULL CONSTRAINT [DF_dblock_information_TransDateTime] DEFAULT (getdate()),
[AppName] [varchar](50) NULL,
[HostName] [varchar](50) NULL,
CONSTRAINT [PK_dblock_information] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

4.2 存储的创建脚本

Create procedure [dbo].[dblockcheck]
@AlarmThreshold as tinyint=10
as
set nocount on
--------------------------------------------------------------------------------------------------------
--*Program*: <dblock check for job>
--*Programer*:<>
--*Date*:<>
--*Description*:<Query SQL Locking Process>
--*Unify*:<UA>
--########## Parameter Description Begin ########## --########## Parameter Description End # ########## --##########Update Log Begin ###################
--##########Update Log End # ###################
--------------------------------------------------------------------------------------------------------
declare @SQL as varchar(200)
declare @Subject as varchar(200)
declare @Body as nvarchar(max)
declare @SPName as nvarchar(max)
declare @Message as nvarchar(200)
declare @DBname varchar(15)
declare @IP varchar(20)
declare @CNT as int
declare @cnt2 int
declare @IndividualQuery nvarchar(1000)
declare @HostName varchar(50)
declare @AppName varchar(50)
SET @DBname=DB_NAME() SELECT @IP='XXX.XXX.XXX.XXX'
----不手动定义IP也可通过以下函数来实现
Declare @ServerIP NVARCHAR(30)='', @SERVERNAME NVARCHAR(60)=''
SELECT top 1 @SERVERNAME = @@SERVERNAME ,@ServerIP=LOCAL_NET_ADDRESS
FROM SYS.DM_EXEC_CONNECTIONS where LOCAL_NET_ADDRESS is not null
--------
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) create table #tmp_lock_information (
id int identity(1,1),
Message nvarchar(200),
LockType char(1),
SPID1 int,
SPID2 int,
EventType nvarchar(100),
Parameters nvarchar(10),
EventInfo nvarchar(max),
IndividualQuery nvarchar(1000),
AppName varchar(50),
HostName varchar(50)
) IF @@ERROR<>0 RETURN @@ERROR
insert into #tmp_lock_who(spid,bl)
select 0 ,blocked
from (select * from master..sysprocesses where blocked>0 ) a
where not exists(select * from (select * from master..sysprocesses where blocked>0 ) b
where a.blocked=spid)
union
select spid,blocked from master..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 N'现在没有阻塞信息!' as message
-- 循环开始
while @intCounter <= @intCountProperties
begin
-- 取第一条记录
select @spid = spid,@bl = bl
from #tmp_lock_who where Id = @intCounter
begin
SELECT @IndividualQuery= SUBSTRING (qr.text,qs.statement_start_offset/2,
(CASE WHEN qs.statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX), qr.text)) * 2
ELSE qs.statement_end_offset END - qs.statement_start_offset)/2)
FROM SYS.DM_EXEC_REQUESTS qs OUTER APPLY SYS.DM_EXEC_SQL_TEXT(qs.sql_handle) AS qr
WHERE qr.text is not null and qs.session_id=@bl
select @HostName=left(HostName,50),@AppName=Left(Program_Name,50)
from master..sysprocesses With(nolock) Where SPID=@bl
set @SQL='DBCC INPUTBUFFER ('+cast(@bl as char(20))+')'
if @spid =0
begin
select @Message=N'引起数据库阻塞的是: '+ CAST(@bl AS NVARCHAR(100)) + N'进程号,其执行的SQL语法如下'
--set @SQL='DBCC INPUTBUFFER ('+cast(@bl as char(20))+')'
insert into #tmp_lock_information(EventType,Parameters,EventInfo) exec(@sql)
update #tmp_lock_information set LockType='',SPID1=@bl,SPID2=@bl,IndividualQuery=@IndividualQuery,[Message]=@Message,AppName=@APPName,HostName=@HostName where [Message] is null
end
else
begin
select @Message=N'进程号SPID:'+ CAST(@spid AS NVARCHAR(100))+ N'被' + N'进程号SPID:'+ CAST(@bl AS NVARCHAR(10)) +N'阻塞,其当前进程执行的SQL语法如下'
insert into #tmp_lock_information(EventType,Parameters,EventInfo) exec(@sql)
update #tmp_lock_information set LockType='', SPID1=@spid,SPID2=@bl,IndividualQuery=@IndividualQuery,[Message]=@Message,AppName=@APPName,HostName=@HostName where [Message] is null
end
end
-- 循环指针下移
set @intCounter = @intCounter + 1
end
drop table #tmp_lock_who
if exists(select 0 from #tmp_lock_information)
Begin Insert into dblock_information(Message,LockType,SPID1,SPID2,EventType,Parameters,EventInfo,IndividualQuery,AppName,HostName)
Select [Message],LockType,SPID1,SPID2,EventType,Parameters,Substring(EventInfo,1,500),IndividualQuery,AppName,HostName from #tmp_lock_information End drop table #tmp_lock_information
return 0
end

SQL Server阻塞的检查的更多相关文章

  1. 需要我们了解的SQL Server阻塞原因与解决方法

    需要我们了解的SQL Server阻塞原因与解决方法 上篇说SQL Server应用模式之OLTP系统性能分析.五种角度分析sql性能问题.本章依然是SQL性能 五种角度其一“阻塞与死锁” 这里通过连 ...

  2. sql server 阻塞与锁

    SQL Server阻塞与锁 在讨论阻塞与加锁之前,需要先理解一些核心概念:并发性.事务.隔离级别.阻塞锁及死锁. 并发性是指多个进程在相同时间访问或者更改共享数据的能力.一般情况而言,一个系统在互不 ...

  3. Sql Server 阻塞的常见原因和解决办法

    1. 由于语句运行时间太长而导致的阻塞,语句本身在正常运行中,只须等待某些系统资源 解决办法: a. 语句本身有没有可优化的空间 b. Sql Server 整体性能如何,是不是有资源瓶颈影响了语句执 ...

  4. SQL Server 阻塞原因分析

    这里通过连接在sysprocesses里字段值的组合来分析阻塞源头,可以把阻塞分为以下5种常见的类型(见表).waittype,open_tran,status,都是sysprocesses里的值,“ ...

  5. SQL Server里面如何检查没有释放的游标

    一直以来对SQL SERVER的游标都不怎么感冒,也很少使用SQL Server里面的游标,前几天有一位网友问如何检查数据库里面没有释放的游标,觉得有点意思,就测试验证了一下,顺便整理于此. 会话1: ...

  6. SQL Server 阻塞分析

    一.加锁(locking).阻塞(blocking).死锁(deadlock)定义        加锁:用于管理多个连接的进程.当连接需要访问一块数据时,在这些数据上放置某种类型的锁.      阻塞 ...

  7. SQL Server 阻塞排除的 2 方法

    背景知识: 是什么造成了阻塞? 从锁的观点来看.可访问对象前一定要对对象加锁不管你是读还是写,如果用户A以经持有对象,说明A以在对象上加锁,如果这时B 也想访问这个对象.它也要对对象加锁.重点来了如果 ...

  8. 一个特殊的SQL Server阻塞案例分析

    上周,在SQL Server数据库下面遇到了一个有意思的SQL阻塞(SQL Blocking)案例.其实个人对SQL Server的阻塞还是颇有研究的.写过好几篇相关文章. 至于这里为什么要总结一下这 ...

  9. SQL Server阻塞诊断

    在数据仓库维护过程中,经常会出现定时更新程序和查询SQL发生冲突而引起阻塞的情况,需要进行SQL Server诊断. SQL Server诊断一般会用到2个视图:sys.sysprocesses(系统 ...

随机推荐

  1. 个性化windows10主题/换成winxp主题

    win10系统主题手动更换为仿winXp系统主题 突然想念家里那台被遗忘了好久的旧电脑,思绪被拉回小时候偷玩电脑的场景. 如果你也是一个念旧的人的话,我相信你一定喜爱Windows XP的经典界面. ...

  2. 036.[转] JNDI 学习

    使用外置服务器(如tomcat)时,如果一个服务器启动多个项目,可以使用JNDI配置数据源,这样每个项目都可以获取到Tomcat 配置的 JNDI的数据源. 在学习 jsp 的时候,作用域对象 pag ...

  3. Druid-代码段-1-1

    所属文章:池化技术(一)Druid是如何管理数据库连接的? 本代码段对应主流程1,具体用来获取一个连接: lic DruidPooledConnection getConnection(long ma ...

  4. JVM-0-JVM知识体系

     

  5. css 知识点,你有可能不知道欧!

    1.[定位特性] 绝对定位和固定定位,同时设置left和right等同于隐式的设置宽度. <style> span{ position:fixed; left:30px; right:30 ...

  6. 201871010136-赵艳强《面向对象程序设计(java)》第一周学习总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/  这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/ ...

  7. 03. Go 语言容器

    Go语言容器(container) 变量在一定程度上能满足函数及代码要求.如果编写一些复杂算法.结构和逻辑,就需要更复杂的类型来实现.这类复杂类型一般情况下具有各种形式的存储和处理数据的功能,将它们称 ...

  8. Go module的两个代理源和设置方法

    Go module的两个代理源 阿里云 https://mirrors.aliyun.com/goproxy/ 使用帮助 1.使用go1.11以上版本并开启go module机制 2.导出GOPROX ...

  9. MySQL数据库实战之优酷

    目录 一.项目总结三步骤 二.项目需求分析 三.搭建框架 四.ORM框架分析 五.数据库设计 六.项目中各个功能模块分析 七.项目中遇到的问题及怎么解决的 八.客户端代码框架 8.1 conf 8.1 ...

  10. something just like this---About Me

    endl:JX弱校oier,04年生,妹子,2019级高一新生,然后居然不知道该说什么了,尴尬 2019年3月开始接触oi,学的很慢(看起来脑子不太好用) 2019年7月创建了这个博客,在收到“恭喜! ...