如何配置 MS SQL 服务器以避免更新锁定 (LCK_M_U)
How do I configure MS SQL server to avoid update lock (LCK_M_U)
我有 MS SQL 服务器,其数据库包含多个 table。每个 table 都有一个字段 'SN'。多个客户端可以使用此数据库,但每个客户端仅使用具有自己的 SN 值的记录进行操作。
一种客户端应用程序是使用 pyodbc 在 python 中编写的遗留软件。据我了解,该软件可以创建长事务——它可以执行 UPDATE 或 INSERT 语句并仅在几个小时后提交它们。我知道这样做是错误的,但修改那个软件是不可取的。
事务隔离级别设置为 READ_COMMITED,READ_COMMITTED_SNAPSHOT 设置为开启。
除以下情况外一切正常:
- 首先,遗留客户端启动更新记录及其 SN 值的事务,比如 SN = 1
- 另一个客户端应用程序尝试使用其 SN 值更新记录,比如 SN = 2
这种情况导致第二个客户端 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?),由于锁升级,无法保证行锁。
我考虑过将事务隔离级别设置为 'READ UNCOMMITTED',但我不确定这是正确的方法。
有什么方法可以正确配置 MS SQL 服务器来解决此锁定并允许 'simultaneous' 更新不同的行?
在 SN
上分区可能是最好的方法。您可以使用另一种方法,但请谨慎使用。您可以通过启用跟踪标志 1211 来禁用锁定升级。但是,此跟踪标志会在 SQL 服务器实例中全局禁用所有锁定升级。锁升级在 SQL 服务器中非常有用,它可以最大限度地提高查询效率,否则这些查询会因获取和释放数千个锁的开销而减慢。锁升级还有助于最小化跟踪锁所需的内存。 SQL 服务器可以为锁结构动态分配的内存是有限的,因此如果禁用锁升级并且锁内存增长到足够大,尝试为任何查询分配额外的锁可能会失败。
我找到了一个似乎适合我的解决方案。它在 this topic on microsoft forum 中有描述。这个想法是为表中的 SN 字段创建索引,如下所示:
CREATE INDEX IX_SN ON TABLE_NAME(SN)
我有 MS SQL 服务器,其数据库包含多个 table。每个 table 都有一个字段 'SN'。多个客户端可以使用此数据库,但每个客户端仅使用具有自己的 SN 值的记录进行操作。
一种客户端应用程序是使用 pyodbc 在 python 中编写的遗留软件。据我了解,该软件可以创建长事务——它可以执行 UPDATE 或 INSERT 语句并仅在几个小时后提交它们。我知道这样做是错误的,但修改那个软件是不可取的。
事务隔离级别设置为 READ_COMMITED,READ_COMMITTED_SNAPSHOT 设置为开启。
除以下情况外一切正常:
- 首先,遗留客户端启动更新记录及其 SN 值的事务,比如 SN = 1
- 另一个客户端应用程序尝试使用其 SN 值更新记录,比如 SN = 2
这种情况导致第二个客户端 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?),由于锁升级,无法保证行锁。
我考虑过将事务隔离级别设置为 'READ UNCOMMITTED',但我不确定这是正确的方法。
有什么方法可以正确配置 MS SQL 服务器来解决此锁定并允许 'simultaneous' 更新不同的行?
在 SN
上分区可能是最好的方法。您可以使用另一种方法,但请谨慎使用。您可以通过启用跟踪标志 1211 来禁用锁定升级。但是,此跟踪标志会在 SQL 服务器实例中全局禁用所有锁定升级。锁升级在 SQL 服务器中非常有用,它可以最大限度地提高查询效率,否则这些查询会因获取和释放数千个锁的开销而减慢。锁升级还有助于最小化跟踪锁所需的内存。 SQL 服务器可以为锁结构动态分配的内存是有限的,因此如果禁用锁升级并且锁内存增长到足够大,尝试为任何查询分配额外的锁可能会失败。
我找到了一个似乎适合我的解决方案。它在 this topic on microsoft forum 中有描述。这个想法是为表中的 SN 字段创建索引,如下所示:
CREATE INDEX IX_SN ON TABLE_NAME(SN)