【问题标题】:Data locks caused by non-committed transactions未提交事务导致的数据锁
【发布时间】:2017-05-17 20:31:13
【问题描述】:

我的 Web 应用程序连接到 SQL Server 2016 Express 数据库,我们一直受到系统某些区域的数据锁的困扰。

我的同事今天注意到,当使用 KILL 进程终止一个长时间运行的事务时,几个表面上已经提交的事务被回滚了。

我在In SQL Server, how do I know what transaction mode I'm currently using? 上使用@vladV 的脚本检查了实际上数据库似乎处于自动提交模式。

因此,必须是数据库中的某些东西正在打开一个新事务而不是提交它。

于是我在数据库中找到了四个存储过程,其中包含以下内容

SET  IMPLICIT_TRANSACTIONS  ON
... code ...
IF @@TRAN_COUNT>0 COMMIT WORK

我是否正确地说,在某些/大多数情况下,即使在退出存储过程之后,这样的存储过程也会使事务保持打开状态,这可能是数据锁定问题的根源?

如果是这样,那么我可以通过这样做来纠正代码

SET IMPLICIT_TRANSACTIONS OFF 

存储过程何时退出?

【问题讨论】:

  • 可以帮助您的东西:SET IMPLICIT_TRANSACTIONS。看起来你的问题的答案是肯定的。当然,您应该对其进行测试以确定。
  • 如果您使用 SQL Express,您的数据库很小,所有查询都应该非常快。也许最好优化您的长时间运行的事务以更快地运行。
  • @R.理查兹 - 好的 - 谢谢。我会尝试...
  • @MikhailLobanov - 同意!但我认为在大多数情况下它们长时间运行的原因是因为数据锁!
  • @gordon613 你也可以尝试其他事务隔离级别(例如SNAPSHOT)。每个隔离级别都有自己的锁数

标签: sql-server


【解决方案1】:

我说得对吗?在某些/大多数情况下,这样的存储过程会使事务保持打开状态

一些。取决于后面的事情。使用 SQL Server 中的隐式事务,在您运行读取数据库的查询之前,事务不会自动启动。

我可以通过执行 SET IMPLICIT_TRANSACTIONS OFF 来修正代码

没有。这不会结束任何未完成的交易。

请注意,COMMIT 不会将@@trancount 减为 0。它会减 1。因此,如果您有多个 BEGIN TRAN 语句,或者在事务隐式开始后有一个显式 BEGIN TRAN,那么您将需要多个 COMMIT .

你可以试试

WHILE @@trancount > 0 COMMIT TRANSACTION

这肯定会提交任何未完成的交易。

【讨论】:

  • 谢谢!如果我用 BEGIN TRANSACTION 替换 SET IMPLICIT TRANSACTIONS ON 并用 COMMIT TRANSACTION 替换 SET IMPLICIT TRANSACTIONS OFF 可能会更好。你怎么看?
  • 我更喜欢使用隐式事务,并明确地处理所有事务。所以这是一个很好的方向,但更多的是改变。
  • 好的。我将重写存储过程以仅使用显式事务。
猜你喜欢
  • 1970-01-01
  • 2011-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-12
  • 1970-01-01
相关资源
最近更新 更多