除了内存、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_informationorder by TransDateTime desc4.代码实现
4.1 table的创建脚本
CREATE table [dbo].dblock_information]( ID] intIDENTITY(1,1) NOT NulL,Messagenvarchar](300) LockTypechar1) SPID1] SPID2EventType100) Parameters10) EventInfo3000) IndivIDualquery1000) TransDateTimedatetimeNulL CONSTRAINT DF_dblock_information_TransDateTime] DEFAulT (getdate()),1)">Appnamevarchar50) HostnamePK_dblock_informationPRIMARY KEY CLUSTERED ( ASC)WITH (PAD_INDEX = OFF,STATISTICS_norECOmpuTE ON,ALLOW_PAGE_LOCKS ON) ON PRIMARY) ]
4.2 存储的创建脚本
Create procedure dblockcheck] @AlarmThreshold as tinyint=10 asset 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 varchar(200)@Subject @Body nvarchar(max@SPname @Message nvarchar(@DBname 15@IP 20@CNT int@cnt2 @IndivIDualquery 1000@Hostname 50@Appname SET @DBname=DB_name()SELECT @IP'XXX.XXX.XXX.XXX'--不手动定义IP也可通过以下函数来实现Declare @ServerIP NVARCHAR(30)'',@SERVERname 60)'' 1 @SERVERname @@SERVERname,1)">@ServerIP=LOCAL_NET_ADDRESS FROM SYS.DM_EXEC_CONNECTIONS where LOCAL_NET_ADDRESS is not null------begin @spID int,1)">@bl int@intTransactionCountOnEntry @intRowcount @intCountPropertIEs @intCounter intcreate table #tmp_lock_who ( ID int IDentity(1),spID smallint) #tmp_lock_information ( ID char(10010) )IF @@ERROR<>0 RETURN @@ERROR insert into #tmp_lock_who(spID,bl) select 0from (from master..sysprocesses where blocked> ) a where not exists( ) b where a.blockedspID) union select spID,blocked 0 找到临时表的记录数 @intCountPropertIEs = Count(*),1)">@intCounter = 1 #tmp_lock_who @@ERROR if @intCountPropertIEs0 select N现在没有阻塞信息!' as message 循环开始 while <= @intCountPropertIEs begin 取第一条记录 @spID = spID,1)">@bl bl from #tmp_lock_who where ID @intCounter begin @IndivIDualquerySUBSTRING (qr.text,qs.statement_start_offset/2CASE WHEN qs.statement_end_offset -THEN LEN(CONVERT(NVARCHAR(MAX),qr.text)) * 2 ELSE qs.statement_end_offset END - qs.statement_start_offset)) FROM SYS.DM_EXEC_REQUESTS qs OUTER APPLY SYS.DM_EXEC_sql_TEXT(qs.sql_handle) AS qr WHERE qr.text null and qs.session_ID@bl @Hostname=left(Hostname,1); Font-weight: bold">50),1)">@Appname=left(Program_name,1)">) With(nolock) Where SPIDset @sqlDBCC inputBUFFER ('+cast(20)))' 0 begin @Message=N引起数据库阻塞的是: + CAST(AS 100)) + N进程号,其执行的sql语法如下' set @sql='DBCC inputBUFFER ('+cast(@bl as char(20))+')' into #tmp_lock_information(EventType,Parameters,EventInfo) exec(@sql) update #tmp_lock_information set LockType1',SPID1@bl,SPID2@IndivIDualquery,]@Message,Appname@APPname,Hostnamewhere is null end else 进程号SPID:100))被' 10)) +N阻塞,其当前进程执行的sql语法如下2@spID,1)">end end 循环指针下移 + 1 end drop #tmp_lock_who if #tmp_lock_information) Begin Insert dblock_information(Message,LockType,SPID1,SPID2,EventType,EventInfo,IndivIDualquery,Appname,Hostname) Select ],1)">Substring(EventInfo,1); Font-weight: bold">500),Hostname #tmp_lock_information End #tmp_lock_information return 0end
总结
以上是内存溢出为你收集整理的SQL Server阻塞的检查全部内容,希望文章能够帮你解决SQL Server阻塞的检查所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)