3

众所周知,有两种锁定策略:Optimistic vs. Pessimistic locking使用乐观锁定时可能会出现死锁吗?

悲观锁定是,当你锁定该记录为您独家使用 ,直到你完成它。它比 乐观锁定具有更好的完整性,但要求您注意应用程序设计以避免Deadlocks

而且knonw,即Optimistic Concurrency Control是不一样的Multi Version Concurrency Control(Oracle或MSSQL快照/ MVCC-RC):Optimistic vs Multi Version Concurrency Control - Differences?

但是,如果在这两个使用OCC(Optimistic Concurrency Control)两笔交易之间可以发生死锁?

我们可以说乐观锁定通过降低一致性来减少死锁的可能性吗?只有每次更新都在单独的事务中,那么死锁的可能性为0%,但这是最小的一致性。

回答

3

当然。

死锁只是意味着线程A拥有一个锁,线程B正在等待,而B持有A正在等待的锁。如果您的应用程序不是按照相同顺序锁定资源的,则无论您的锁定策略如何,都很容易死锁。

想象一下,线程A和B都希望更新父表和子表中的特定行。线程A首先更新父行。线程B首先更新子行。现在,线程A尝试更新子行并发现自己被B阻止。同时,线程B尝试更新父级并发现自己被A阻止。您有一个死锁。

如果您在Oracle中拥有一致的锁定资源顺序(即始终在子级之前锁定父级),则不管您的锁定策略如何,都不会发生死锁。您通常不会在SQL Server中导致死锁,但是在SQL Server中升级行级锁的可能性不足以确定。

+0

谢谢!因此Oracle数据库永远不会升级锁。锁定升级大大增加了死锁的可能性。这是否意味着死锁是多版本并发的另一个差异乐观并发?但目前,在完成乐观并发时 - 读取 - 检查 - 修改行时,我们是否使用锁定?或者每次交易只能有一个锁定,所以不能成为死锁。 – Alex

+1

@亚历山大 - 我不确定我是否了解跟进。为了更新一行,你必须锁定它。乐观和悲观锁定之间的区别在于,您是否悲观地锁定行以防万一您可能会更新它,或者乐观地等待,直到您知道要更新它以获取锁定。您可以编写一个应用程序,将每次更新作为单独的事务处理。这样可以减少死锁,但对于数据一致性来说会很糟糕。 –

+0

是的,谢谢,这就是我想知道的。我们可以说乐观锁定通过降低一致性来减少死锁的可能性吗?只有在单独事务中的每次更新时,死锁的可能性都是0%,但这是最小的一致性。使用一定数量的乐观方法,我们可以在死锁和一致性之间取得必要的平衡。 – Alex

1

恐怕您在乐观并发控制的定义中必须非常精确。在Bernstein,Goodman和Hadzilacos的经典定义中,乐观并发控制允许线程“虚拟”获取锁,继续更新,然后在事务尝试提交时检查一致性违规。如果发生一致性违规,则该事务将被迫中止并重新提交。在这个定义下,不清楚死锁是如何发生的,因为线程“永不”被阻塞等待锁定。乐观并发控制的经典定义并不容易实现。然而,最近在硬件事务内存方面的工作正在开启一些可能性,并对这个老问题提出一些看法。

+0

谢谢!但是使用硬件事务存储器实现的乐观并发控制的经典定义 - 它是否可以具有属性可组合性? https://en.wikipedia.org/wiki/Software_transactional_memory#Composable_operations – Alex

+0

此外,使用“可调整隔离级别”时出现死锁的可能性最小,当任何修改仅在事务提交后才可见时,Tom Kyte说“可串行化是实现高吞吐量和更快响应时间的一种方式“,从中可以得出线程碰撞较少的结论。 https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:12684560615138这是真的,通过使用OCC可以在MVCC中只实现可调整的隔离级别,或者也可以其他:阅读提交,可重复阅读,快照? – Alex