通过使用NOLOCK提示来避免死锁。

18 浏览
0 Comments

通过使用NOLOCK提示来避免死锁。

生产环境偶尔会出现以下错误,但再次运行相同的存储过程后该错误即会消失。

事务(进程 ID 86)在锁资源上与另一个进程发生死锁,因此被选择为死锁牺牲者。请重新运行该事务。

有人告诉我,如果在我的存储过程中使用NOLOCK提示,它将确保不会发生死锁。这个说法正确吗?还有其他更好的处理此错误的方法吗?

0
0 Comments

避免使用NOLOCK提示来避免死锁的问题是因为在多个并发的事务中,当一个事务持有资源并等待其他事务释放资源时,可能会发生死锁。解决方法是使用其他锁定提示,如READPAST和UPDLOCK,来替代NOLOCK提示。

以下是解决方法的示例代码:

SELECT * FROM table WITH(READPAST)

使用READPAST提示可以避免读取已被其他事务锁定的行。这样可以避免死锁发生,但是可能会导致丢失一些数据。

SELECT * FROM table WITH(UPDLOCK)

使用UPDLOCK提示可以在读取行时立即对其进行排他锁定,这样可以防止其他事务对该行进行修改。这种方法可以避免死锁发生,但是可能会导致其他事务等待锁的时间增加。

总之,避免使用NOLOCK提示可以有效地减少死锁的发生。通过使用其他锁定提示,我们可以更好地控制事务对资源的访问,从而避免死锁的发生。

0
0 Comments

避免使用NOLOCK提示出现死锁的原因是:NOLOCK提示可以防止读取和写入彼此阻塞,但它并不能完全解决死锁问题。许多死锁与数据读取无关,因此对读取查询应用NOLOCK提示可能不会产生任何变化。你是否运行了跟踪并检查了死锁图,以确定死锁的具体原因?这至少可以让你知道要查看哪部分代码。例如,存储过程是否因为被多个用户同时调用而发生死锁,还是与其他代码发生死锁?

在数据库写入(插入、更新、删除)时,NOLOCK提示不起作用。

虽然如此,我的观点只是在默认的隔离级别下,写入操作可能会被阻塞,等待读取操作完成。(抱歉,不确定你是在确认我所说的,还是在反驳。:-))

这只是对在同一段落中同时使用"NOLOCK"和"魔法修复"的反应。我确信你知道它是如何工作的,我只是试图阻止常见的误解,即NOLOCK可以用来防止插入和更新操作膨胀事务日志文件。

解决方法:根据跟踪和死锁图的分析结果,检查代码的具体部分,查看存储过程是否被多个用户同时调用,或者与其他代码发生死锁。避免使用NOLOCK提示作为解决死锁的唯一手段,因为它并不能完全解决死锁问题。

0
0 Comments

避免使用NOLOCK提示的死锁问题可能出现的原因是:在使用像SQL Server/Sybase这样会锁定的关系数据库管理系统(RDBMS)时,偶尔会出现死锁情况。解决方法是在客户端上编写代码,根据MSDN上的“处理死锁”建议进行重试。基本上,检查SQLException,然后在大约半秒钟后再次尝试。否则,应该检查代码,确保对表的所有访问都按照相同的顺序进行。或者可以使用SET DEADLOCK_PRIORITY来控制谁成为死锁的受害者。

在SQL Server的MSDN上有“最小化死锁”的文档,其中提到:

尽管无法完全避免死锁

它还提到“使用较低的隔离级别”,这不是我喜欢的方法(与许多SQL类型一样),也是你的问题。不要这样做是答案... 🙂

以下是相关问题的链接:

- [What can happen as a result of using (nolock) on every SELECT in SQL Server?](https://stackoverflow.com/q/1682240/27535)

- [https://dba.stackexchange.com/q/2684/630](https://dba.stackexchange.com/q/2684/630)

请注意:MVCC类型的RDBMS(如Oracle、Postgres)不存在这个问题。请参阅[http://en.wikipedia.org/wiki/ACID#Locking_vs_multiversioning](http://en.wikipedia.org/wiki/ACID#Locking_vs_multiversioning),但是MVCC也有其他问题。

如果使用了READ COMMITTED SNAPSHOT来消除读锁,并且确保每个更新/删除语句以相同的顺序获取锁(可能按字母顺序),难道就不能完全避免死锁吗?问题是实现这个逻辑是否困难或者不值得费力?(我还没有尝试过,但是我正在考虑这个方法,因为我自己遇到了死锁问题)

0