如何解决 sql 中的 lck_m_x Lock

Posted

技术标签:

【中文标题】如何解决 sql 中的 lck_m_x Lock【英文标题】:How to solve lck_m_x Lock in sql 【发布时间】:2012-04-03 10:00:50 【问题描述】:

我有一个复杂的查询(没有任何锁定提示),它从许多表中获取数据,比如 Table1、Table2、Table3

下面是检索数据的代码(没有交易)

  IDbCommand sqlCmd = dbHelper.CreateCommand(Helper.MyConnString, sbSQL.ToString(), CommandType.Text, arParms);
  sqlCmd.CommandTimeout = 300;
  ds = dbHelper.ExecuteDataset(sqlCmd);

在应用程序中,此查询每 2 分钟运行一次

当我触发一个简单的更新查询时说

Update Table1 set Col1='abc' where ID=100  

(其中 ID 是 int 和主键 + 聚集索引)

更新查询被延迟并且多次超时 下面是日志

我该如何解决这个问题。

【问题讨论】:

【参考方案1】:

您可以在隔离级别为 SNAPSHOT 的事务中执行查询。这样,您的查询将不会获取任何(共享)锁,并且您的 UPDATE 不必等待排他锁(假设表上阻止您的 UPDATE 的锁的来源实际上是应用程序运行的查询每两分钟...)

作为参考,请查看 MSDN 上的 Working with Snapshot Isolation 和 SET TRANSACTION ISOLATION LEVEL。

因评论而编辑:

首先,为您的数据库启用 ALLOW_SNAPSHOT_ISOLATION:

ALTER DATABASE YourDB SET ALLOW_SNAPSHOT_ISOLATION ON

然后,将查询编写如下:

SET TRANSACTION ISOLATION LEVEL SNAPSHOT;

SELECT      Column1, Columns2, ...
FROM        Table1
LEFT JOIN   Table2
ON          Table1.Columns45 = Table2.Column3
[... your complex query ...]

举个例子就够了吗?

【讨论】:

你能举个小例子吗?【参考方案2】:

如果您不想在修改数据时等待读取查询,最好使用READ_COMMITTED_SNAPSHOT。

可以透明开启,不影响你的应用代码,没有副作用。

SNAPSHOT 有很多副作用,例如,虽然您没有锁定数据修改,但您在提交时可能会遇到数据冲突问题,这个问题非常难以处理。

【讨论】:

以上是关于如何解决 sql 中的 lck_m_x Lock的主要内容,如果未能解决你的问题,请参考以下文章

mysql lock 锁表

求助sqlserver服务器压力问题

变基时 Gemfile.lock 中的冲突

Lock解决Lock问题

如何防止用餐哲学家c ++中的死锁

21.Lock锁原理