博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SQLServer数据库优化与管理——锁,阻塞,死锁篇
阅读量:3761 次
发布时间:2019-05-22

本文共 6202 字,大约阅读时间需要 20 分钟。

1侦测阻塞问题

阻塞会发生在很多情况下,它会引起终端用户的响应时间变长。而且由于锁住了数据,
可能会得不到想要的结果,甚至会产生连接超时等问题。
sQL Server提供了–些工具来侦测基于锁的阻塞,比如相关的DMVs、性能监视器、
SQLDiag等。下面来简要介绍一下。
.1) PerfMon counters为性能监视器,其中SQL Server:General Statistics事件中的
Processes blocked计数器,显示被阻塞进程的数量。还可以在SQL Server:Wait Statistics事
件的Lock Waits计数器中查看锁的数量和锁的持续时间。但是得到的只是概要信息。
2 ) DMVs:可以使用sys.dm_os_waiting_tasks来返回当前正在等待的任务信息。对于
这个DMV的说明,请查阅联机丛书。注意DMV 返回的是任务级别的信息,而不是会话级
别的,如果-个查询是并行运行,其中一个线程被阻塞,这个DMV只会显示这个线程的信
息。某些情况下,sys.dm_os_waiting_tasks中 blocking_session_id可能为null,因为没有正
在阻塞的会话,或者SQL Server无法标识这个会话。但是在以下情形下blocking_session_.
id会出现负数。
-2:被锁定的资源属于一个孤立的分布式事务。
-3:被锁定的资源属于–个延迟恢复事务。
.
-4:门锁等待。
下面是查看阻塞持续时间超过5000ms的会话。

SELECT  W.session_id AS waiting_session_id ,         W.waiting_task_address ,         W.wait_duration_ms ,         W.wait_type ,         W.blocking_session_id ,         W.resource_description FROM    sys.dm_os_waiting_tasks AS W WHERE   W.wait_duration_ms > 5000         AND blocking_session_id IS NOT NULL;

也可以用下面的语句查看库内所有在WAIT状态的锁,并了解它们在等待什么锁。

USE AdventureWorks2008R2GO SELECT  L1.resource_type ,        DB_NAME(L1.resource_database_id) AS DatabaseName ,        CASE L1.resource_type          WHEN 'OBJECT'          THEN OBJECT_NAME(L1.resource_associated_entity_id,                           L1.resource_database_id)          WHEN 'DATABASE' THEN 'DATABASE'          ELSE CASE WHEN L1.resource_database_id = DB_ID()                    THEN ( SELECT   OBJECT_NAME(object_id,                                                L1.resource_database_id)                           FROM     sys.partitions                           WHERE    hobt_id = L1.resource_associated_entity_id                         )                    ELSE NULL               END        END AS ObjectName ,        L1.resource_description ,        L1.request_session_id ,        L1.request_mode ,        L1.request_statusFROM    sys.dm_tran_locks AS L1        JOIN sys.dm_tran_locks AS L2 ON L1.resource_associated_entity_id = L2.resource_associated_entity_idWHERE   L1.request_status <> L2.request_status        AND ( L1.resource_description = L2.resource_description              OR ( L1.resource_description IS NULL                   AND L2.resource_description IS NULL                 )            )ORDER BY L1.resource_database_id ,        L1.resource_associated_entity_id ,        L1.request_status ASC;

返回阻塞的信息及相关语句。

SELECT  T.session_id AS waiting_session_id ,        DB_NAME(L.resource_database_id) AS DatabaseName ,        T.wait_duration_ms / 60000. AS duration_in_minutes ,        T.waiting_task_address ,        L.request_mode ,        ( SELECT    SUBSTRING(Q.text, ( R.statement_start_offset / 2 ) + 1,                              ( ( CASE R.statement_end_offset                                    WHEN -1 THEN DATALENGTH(Q.text)                                    ELSE R.statement_end_offset                                  END - R.statement_start_offset ) / 2 ) + 1)          FROM      sys.dm_exec_requests AS R                    CROSS APPLY sys.dm_exec_sql_text(R.sql_handle) AS Q          WHERE     R.session_id = L.request_session_id        ) AS waiting_query_text ,        L.resource_type ,        L.resource_associated_entity_id ,        T.wait_type ,        T.blocking_session_id ,        T.resource_description AS blocking_resource_description ,        CASE WHEN T.blocking_session_id > 0             THEN ( SELECT  ST2.text                    FROM    sys.sysprocesses AS P                            CROSS APPLY sys.dm_exec_sql_text(P.sql_handle) AS ST2                    WHERE   P.spid = T.blocking_session_id                  )             ELSE NULL        END AS blocking_query_textFROM    sys.dm_os_waiting_tasks AS T        JOIN sys.dm_tran_locks AS L ON T.resource_address = L.lock_owner_addressWHERE   T.wait_duration_ms > 5000        AND T.session_id > 50;

在 Extended Events中,默认的事件会话是system_health,用于收集 SQL Server发生

的错误,包括死锁信息。system_health会话使用-个名为ring_buffer的目标,来收集内存
中的事件信息,然后以XML格式存储在sys.dm_xe_session_targets 这个DMV中。另外可
以把这个DMV通过关联另外-个DMV: sys.dm_xe_sessions,获取相关信息。下面是查询
死锁信息的语句:

USE MasterGOSELECT  xed.value('@timestamp', 'datetime') AS Creation_Date ,        xed.query('.') AS Extend_EventFROM    ( SELECT    CAST([target_data] AS XML) AS Target_Data          FROM      sys.dm_xe_session_targets AS xt                    INNER JOIN sys.dm_xe_sessions AS xs ON xs.address = xt.event_session_address          WHERE     xs.name = N'system_health'                    AND xt.target_name = N'ring_buffer'        ) AS XML_Data        CROSS APPLY Target_Data.nodes('RingBufferTarget/event[@name="xml_deadlock_report"]')        AS XEventData ( xed )ORDER BY Creation_Date DESC

下面的DMV代码可以用来捕获阻塞信息。

SELECT  dtl.request_session_id AS WaitingSessionID ,        der.blocking_session_id AS BlockingSessionID ,        dowt.resource_description ,        der.wait_type ,        dowt.wait_duration_ms ,        DB_NAME(dtl.resource_database_id) AS DatabaseName ,        dtl.resource_associated_entity_id AS WaitingAssociatedEntity ,        dtl.resource_type AS WaitingResourceType ,        dtl.request_type AS WaitingRequestType ,        dest.[text] AS WaitingTSql ,        dtlbl.request_type BlockingRequestType ,        destbl.[text] AS BlockingTsqlFROM    sys.dm_tran_locks AS dtl        JOIN sys.dm_os_waiting_tasks AS dowt ON dtl.lock_owner_address = dowt.resource_address        JOIN sys.dm_exec_requests AS der ON der.session_id = dtl.request_session_id        CROSS APPLY sys.dm_exec_sql_text(der.sql_handle) AS dest        LEFT JOIN sys.dm_exec_requests derbl ON derbl.session_id = dowt.blocking_session_id        OUTER APPLY sys.dm_exec_sql_text(derbl.sql_handle) AS destbl        LEFT JOIN sys.dm_tran_locks AS dtlbl ON derbl.session_id = dtlbl.request_session_id;

其中resource_description列的值如下(不同的机器值会不-一样):

ridlock fileid=1 pageid=411 dbid=2 id=lock368aab480 mode=X associatedObject-
Id–4395513238772318208
对于dbid=2,通过SELECT Db_name(2)可以知道是在TempDB中运行。mode=-X,证明
加上了排他锁,因为已经在实际 UPDATE,所以已经从U锁升级到X锁。至于associatedObj
ectld=4395513238772318208.前而已经提讨,可用以下代码查看:

SELECT OBJECT_MAME(i.objectid),.i.nameFROM-sys.partitions AS p·INNER JoIN sys.indexes As i ON i.object_id=p.object_id AND i.index_id=p.index_idwHERE p.partition_id - 4395513238772318208,

转载地址:http://msesn.baihongyu.com/

你可能感兴趣的文章
相对布局
查看>>
基于媒体库音乐播放器
查看>>
绘制兔子
查看>>
联系人
查看>>
绑定与解除服务
查看>>
阅读古诗
查看>>
初探MyBatis框架
查看>>
利用MyBatis实现CRUD操作
查看>>
利用MyBatis实现关联查询
查看>>
初探Spring——采用Spring配置文件管理Bean
查看>>
初探Spring——利用组件注解符精简Spring配置文件
查看>>
三表关联查询
查看>>
利用MyBatis实现条件查询
查看>>
周总结01
查看>>
周总结02
查看>>
初探Spring——利用注解配置类取代Spring配置文件
查看>>
初探Spring——采用Java配置类管理Bean
查看>>
周总结03
查看>>
Spring AOP基础
查看>>
Spring JdbcTemplate入门
查看>>