【问题标题】:Is it possible to force row level locking in SQL Server?是否可以在 SQL Server 中强制行级锁定?
【发布时间】:2010-06-25 00:23:38
【问题描述】:

我可以看到如何在 SQL Server 中关闭行级和页级锁定,但我找不到强制 SQL Server 使用行级锁定的方法。有没有办法强制 SQL Server 使用行级锁定而不使用页级锁定?

【问题讨论】:

  • 主要问题是:为什么你首先要这样做??
  • 我有两条 SQL 语句陷入死锁,这是我没想到的。见:stackoverflow.com/questions/3112699/…
  • @marc_s 我也有同样的需要。你知道为什么吗?我有一个 sp 需要并行运行,并且我有多个表的代码要被大量行修改。不知道为什么这不应该被视为有效和自然的需要。问题是它导致 SQL Server 死锁..
  • 我也有同样的需求。取出行级锁对于某些算法的正确运行是绝对必要的功能。为了以一种避免死锁的方式取出锁的,它们必须按定义好的全局顺序进行排序和取出(例如,如果行ID是整数,则锁定集合按升序或降序排列)。当数据库引擎任意将行锁升级为页锁时,页锁会无意中破坏锁定顺序,因为它们最终会锁定恰好在该页上的具有不相关 ID 的行。

标签: sql-server sql-server-2005 sql-server-2008 rowlocking


【解决方案1】:

您可以使用 ROWLOCK 提示,但如果资源不足,AFAIK SQL 可能会决定升级它

From the doco:

ROWLOCK 指定行锁是 当页或表锁被占用时 通常采取。当指定在 在 SNAPSHOT 上运行的事务 隔离级别,行锁不是 除非 ROWLOCK 与 其他需要锁的表提示, 例如 UPDLOCK 和 HOLDLOCK。

锁定提示 ROWLOCK、UPDLOCK 和 XLOCK 获取行级锁可能会放置 锁定索引键而不是 实际数据行。例如,如果一个 表有一个非聚集索引和一个 使用锁定提示的 SELECT 语句是 由覆盖索引处理,锁是 在索引键上获取 覆盖索引而不是数据 基表中的行。

And finally 这对 SQL Server 2005 中的锁升级进行了非常深入的解释,而 SQL Server 2008 中对此进行了更改。

还有,非常深入:Locking in The Database Engine(在线书籍中)

一般来说

UPDATE
Employees WITH (ROWLOCK)
SET Name='Mr Bean'
WHERE Age>93

应该没问题,但是根据服务器上的索引和负载,它可能最终升级为页面锁定。

【讨论】:

  • 只是补充一下,在 sql server 2008+ 中,您可以使用 ALTER TABLE tableName SET (LOCK_ESCALATION=DISABLE) 有效地禁用锁升级
  • [基于您对 Remus Rusanu 的 cmets] 意味着我们根本无法锁定一行,Oracle 是如何做到的?
  • @bjan 不确定,一般来说,oracle 的快照特性意味着它不太容易出现这种锁定需求。一般来说,我会避免任何几乎从不需要的行锁提示
  • 你能解释一下为什么不需要它,如果你需要一个问题来回答,我会发布它
  • "它可能最终升级为页面锁定。"根据 BOL,这是不可能的:“数据库引擎不会将行锁或键范围锁升级为页锁”technet.microsoft.com/en-us/library/ms184286(v=sql.105).aspx
【解决方案2】:

使用ALTER/CREATE INDEX的ALLOW_PAGE_LOCKS子句:

ALTER INDEX indexname ON tablename SET (ALLOW_PAGE_LOCKS = OFF);

【讨论】:

  • 一个重要的注意事项是,如果资源不足,这可能会升级为表锁
  • @Sam:详细信息 ;) 广告中的真相:我永远不会在我的数据库中关闭此功能。解决方案始终是正确设计架构和查询,以便一开始就不会发生扫描(这是升级的罪魁祸首)......
  • 完全同意...很少见需要这些技巧然后最终咬你
  • @RemusRusanu 不确定设计或查询的问题 - 原因,为什么我在编写业务逻辑时要担心这一点,至少我没有尝试修改导致问题的其他行.它是 SQL 服务器,它无法足够有效地管理其资源(不像 Oracle),并促使您为此更改代码。如果我必须并行运行某些东西,我们就会无缘无故地陷入混乱。真可惜!
  • @Mashrur 完全同意。
【解决方案3】:

你不能真正强迫优化器做任何事情,但你可以引导它。

UPDATE
Employees WITH (ROWLOCK)
SET Name='Mr Bean'
WHERE Age>93

看 - Controlling SQL Server with Locking and Hints

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-23
    • 1970-01-01
    • 2017-02-08
    • 1970-01-01
    • 2011-05-31
    • 2012-08-03
    • 1970-01-01
    • 2017-01-07
    相关资源
    最近更新 更多