Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2246487
  • 博文数量: 310
  • 博客积分: 6853
  • 博客等级: 准将
  • 技术积分: 2833
  • 用 户 组: 普通用户
  • 注册时间: 2005-08-04 16:41
文章分类

全部博文(310)

文章存档

2013年(17)

2012年(42)

2011年(76)

2010年(71)

2009年(99)

2007年(2)

2006年(1)

2005年(2)

分类: 数据库开发技术

2009-09-16 22:51:39

锁升级(escalate)
与锁的数量有关,达到阀值之后,升级所有连接、所有事物的锁,直接升级到table lock,而不会小升级到page lock

锁升级的时机:

具体细分:将在下列时间触发锁升级:

  • 当单个 Transact-SQL 语句在单个表或索引上获取至少 5,000 个锁时。
  • 当数据库引擎实例中的锁的数量超出了内存或配置阈值时。

如果由于锁冲突导致无法升级锁,则数据库引擎每当获取 1,250 个新锁时便会触发锁升级。

Transact-SQL 语句的升级阈值

当 Transact-SQL 语句在单个表或索引的引用上获取至少 5,000 个锁时,或在表已分区的情况下,在单个表分区或索引分区的引用上获取至少 5,000 个锁时,会触发锁升级。例如,如果该语句在一个索引上获取 3,000 个锁,在同一表中的另一个索引上获取 3,000 个锁,这种情况下不会触发锁升级。同样,如果语句中含有表的自联接,并且表的每一个引用仅在表中获取 3,000 个锁,则不会触发锁升级。

只有触发升级时已经访问的表才会发生锁升级。假定某个 SELECT 语句是一个按 TableATableBTableC 的顺序访问三个表的联接。该语句在 TableA 的聚集索引中获取 3,000 个行锁,在 TableB 的聚集索引中获取至少 5,000 个行锁,但是仍无法访问 TableC。当数据库引擎检测到该语句在 TableB 中获取至少 5,000 个行锁时,会尝试升级当前事务在 TableB 中持有的所有锁。它还会尝试升级当前事务在 TableA 中持有的所有锁,但是由于 TableA 中锁的数量 < 5000,因此,升级无法成功。但它不会尝试在 TableC 中进行锁升级,因为发生升级时尚未访问该表。

数据库引擎实例的升级阈值

每当锁的数量大于锁升级的内存阈值时,数据库引擎都会触发锁升级。内存阈值取决于 locks 配置选项的设置:

  • 如果 locks 选项设置为默认设置 0,当锁对象使用的内存是数据库引擎使用的内存的 24%(不包括 AWE 内存)时,将达到锁升级阈值。用于表示锁的升级结构的长度大约为 100 个字节。此阈值是动态的,因为数据库引擎动态获取并释放内存以适应各种工作负荷。
  • 如果 locks 选项设置为非 0 值,则锁升级阈值是 locks 选项的值的 40%(或者更低,如果存在内存不足的压力)。
数据库引擎可以为升级选择任何会话中的活动语句,而且,只要实例中使用的锁内存保持在阈值之上,每获取 1,250 个新锁,它就会为升级选择语句。


监控锁的数量:

监控锁升级:
可以使用 SQL Server Profiler Lock:Escalation 事件监视锁升级,请参阅。

锁升级的具体对象:

每个升级事件主要在单个 Transact-SQL 语句级别上操作。当事件启动时,只要活动语句满足升级阈值的要求,数据库引擎就会尝试升级当前事务在活动语句所引用的任何表中持有的所有锁。如果升级事件 在语句访问表之前启动,则不会尝试升级该表上的锁。如果锁升级成功,只要表被当前语句引用并且包括在升级事件中,上一个语句中事务获取的、在事件启动时仍 被持有的锁都将被升级。

例如,假定某个会话执行下列操作:

  • 开始一个事务。
  • 更新 TableA。这将在 TableA 中生成排他行锁,直到事务完成后才会释放该锁。
  • 更新 TableB。这将在 TableB 中生成排他行锁,直到事务完成后才会释放该锁。
  • 执行联接 TableATableC 的 SELECT 语句。查询执行计划要求先从 TableA 中检索行,然后才从 TableC 中检索的行。
  • SELECT 语句在从 TableA 中检索行时(此时还没有访问 TableC)触发锁升级。

如果锁升级成功,只有会话在 TableA 中持有的锁才会升级。这包括来自 SELECT 语句的共享锁和来自上一个 UPDATE 语句的排他锁。由于决定是否应进行锁升级时只考虑会话在 TableA 上为 SELECT 语句获取的锁,所以一旦升级成功,会话在 TableA 上持有的所有锁都将被升级到该表上的排他锁,而 TableA 上的所有其他较低粒度的锁(包括意向锁)都将被释放。

不会尝试升级 TableB 上的锁,因为 SELECT 语句中没有 TableB 的活动引用。同样,也不会尝试升级 TableC 上尚未升级的锁,因为发生升级时尚未访问该表。




锁的容量等,可参考 SP_INDEXOPTION.
相关概念:Locking hints (SQL.80).aspx
阅读(3538) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~