当一个数据库会话中的事务正锁定一个或多个其他会话事务想要读取或修改的资源时,会产生阻塞(Blocking)。通常短时间的阻塞没有问题,且是较忙的应用程序所需要的。然而,设计糟糕的应用程序会导致长时间的阻塞,这就不必要地锁定了资源,而且阻塞了其他会话读取和更新它们。
在SQL Server中,一个阻塞的进程会无限期地保持阻塞,或者直到它超时(根据set lock_timeout)、服务器关闭、进程被杀死、连接完成了更新或者其他发生在原始事务上的操作导致它释放了资源上的锁。
发生长时间阻塞的原因如下:
一、找到并解决阻塞进程
下面我们演示使用SQL Server动态管理视图sys.dm_os_waiting_tasks找出阻塞进程,该视图用于代替早期SQL Server版本中的系统存储过程sp_who
找出阻塞的进程后,我们使用sys.dm_exec_sql_text动态管理函数和sys.dm_exec_Connections(DMV)找出正在执行的查询的SQL文本,然后强制结束进程。
强制结束进程,我们使用kill命令。kill的用法,请参看MSDN:http://msdn.microsoft.com/zh-cn/library/ms173730.aspx
该命令有三个参数:
在***个查询窗口:
- BEGIN TRAN
- UPDATE Production.ProductInventory
- SET Quantity = 400
- WHERE ProductID = 1 AND
- LocationID = 1
第二个窗口:
- UPDATE Production.ProductInventory
- SET Quantity = 406
- WHERE ProductID = 1 AND
- LocationID = 1
第三个窗口:
- SELECT blocking_session_id, wait_duration_ms, session_id
- FROM sys.dm_os_waiting_tasks
- WHERE blocking_session_id IS NOT NULL
- /*blocking_session_id wait_duration_ms session_id
- 52 23876 54
- */
可以看出是SessionID为52的会话阻塞了SessionID为54的会话。
那么,52正在干啥坏事呢?在第三个窗口中执行:
- SELECT t.text
- FROM sys.dm_exec_connections c
- CROSS APPLY sys.dm_exec_sql_text (c.most_recent_sql_handle) t
- WHERE c.session_id = 54
- /*text(@1 int,@2 tinyint,@3 tinyint)
- UPDATE [Production].[ProductInventory] set [Quantity] = @1
- WHERE [ProductID]=@2 AND [LocationID]=@3
- */
注意:这并不是***个查询窗口中的原SQL语句,SQL Server进行了自动参数化计划缓存(预编译)。
我们强制终止会话。在第三个窗口中执行:
kill 52 注意:窗口一的语句和窗口二的语句均终止。
提示:第三个语句中,使用sys.dm_exec_connections(DMV)返回了Session ID为53的most_recent_sql_handle列。这是SQL文本在内存中的指针。作为sys.dm_exec_sql_text动态管理函数的输入参数使用。从sys.dm_exec_sql_text返回了text列,该列显示了阻塞进程的SQL文本。如果阻塞成串,必须通过blocking_session_id和session_ID列仔细查看每一个阻塞进程,直到发现原始的阻塞进程。
二、配置语句等待锁释放的时长
如果有一个事务或语句被阻塞,意味着它在等待资源上的锁被释放。我们可以事先通过set lock_Timeout来设定需要等待的时间。
语法如下:SET LOCK_TIMEOUT time_period
参数以毫秒为单位。超过时会返回锁定错误。示例:
在***个窗口中执行:
- USE AdventureWorks
- BEGIN TRAN
- UPDATE Production.ProductInventory
- SET Quantity = 400
- WHERE ProductID = 1 AND
- LocationID = 1
在第二个窗口中执行:
- USE AdventureWorks
- SET LOCK_TIMEOUT 1000
- UPDATE Production.ProductInventory
- SET Quantity = 406
- WHERE ProductID = 1 AND
- LocationID = 1
- /*1秒后的执行结果Msg 1222, Level 16, State 51,Line 3
- Lock request time out period exceeded.
- The statement has been terminated.
- */
解析:在这个示例中,我们设置了锁超时时间为1000毫秒,即1秒。这个设置不会影响资源被进程占有的时间,只会影响等待另一个进程释放资源访问的时间。
原文链接:http://www.cnblogs.com/downmoon/archive/2011/02/18/1957913.html
【编辑推荐】
名称栏目:SQLServer2008中SQL应用之三“阻塞(Blocking)”
当前路径:http://www.csdahua.cn/qtweb/news22/457472.html
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网