如何配置MS SQL服务器以避免更新锁定(LCK_M_U)

时间:2015-04-07 09:34:32

标签: sql-server transactions

我的MS SQL服务器包含一个包含多个表的数据库。每个表都有一个字段' SN'。有几个客户端可以使用这个数据库,但每个客户端只能运行具有自己的SN值的记录。

一种类型的客户端应用程序是使用pyodbc在python中编写的遗留软件。据我所知,该软件可以创建长事务 - 它可以执行UPDATE或INSERT语句,并在几个小时后提交它们。我知道,这样做是错误的,但修改该软件是不可取的。

事务隔离级别设置为READ_COMMITED,READ_COMMITTED_SNAPSHOT设置为ON。

除了以下情况外,一切正常:

  1. 首先,遗留的clent启动事务,UPDATE记录其SN值,比如SN = 1
  2. 另一个客户端应用尝试使用其SN值更新记录,例如SN = 2
  3. 这种情况导致第二个客户端的LCK_M_U锁定: ridlock field = 1 pageid = 311 dbid = 5 id = lock2776cf380 mode = X associatedObjectId = ...这里有很多数字......

    虽然这两个客户端使用不同的SN值,但这会导致锁定。我怀疑这是因为SQL服务器锁不是特定的行,而是一个页面(我想是一组行)。

    根据SO问题(Is it possible to force row level locking in SQL Server?),由于锁定升级,无法保证行锁定。

    我考虑将交易隔离级别设置为“未安装”,但我不确定这是否正确。

    是否有任何方法可以正确配置MS SQL服务器以解决此锁定并允许同时进行'不同行的更新?

2 个答案:

答案 0 :(得分:0)

SN进行分区可能是最好的方法。您可以使用另一种方法,但请谨慎使用。您可以通过启用跟踪标志1211来禁用锁定升级。但是,此跟踪标志会在SQL Server实例中全局禁用所有锁定升级。锁定升级在SQL Server中是一个非常有用的目的,它可以最大限度地提高查询的效率,否则这些查询会因获取和释放数千个锁的开销而减慢。锁定升级还有助于最小化所需的内存以跟踪锁定。 SQL Server可以为锁结构动态分配的内存是有限的,因此如果禁用锁升级并且锁内存增长足够大,则尝试为任何查询分配其他锁可能会失败。

答案 1 :(得分:0)

我找到了一个似乎对我有用的解决方案。它在this topic on microsoft forum中描述。我们的想法是在表格中为SN字段创建索引,如下所示:

CREATE INDEX IX_SN ON TABLE_NAME(SN)