我理解乐观锁定和悲观锁定之间的区别。现在,谁能给我解释一下,我一般什么时候使用这两种方法?

这个问题的答案是否会随着我是否使用存储过程来执行查询而变化?

但是为了检查一下,乐观的意思是“阅读时不要锁定表”,而悲观的意思是“阅读时锁定表”。


当前回答

乐观假设你读的时候什么都不会改变。

悲观的人认为某件事会发生,所以锁定它。

如果数据被完全读取不是必要的,请使用乐观。你可能会得到奇怪的“肮脏”解读——但它不太可能导致死锁或类似的情况。

大多数web应用程序都可以接受脏读——在极少数情况下,下一次重新加载时数据不完全一致。

对于精确的数据操作(如在许多金融交易中)使用悲观。准确读取数据非常重要,没有未显示的更改——额外的锁定开销是值得的。

对了,Microsoft SQL server默认为页面锁定——基本上就是你正在读的那一行和两边的几行。行锁定更准确,但速度要慢得多。通常值得将事务设置为读提交或无锁,以避免读取时发生死锁。

其他回答

我还会想到另外一种情况,悲观锁定会是更好的选择。

对于乐观锁,数据修改的每个参与者都必须同意使用这种锁。但是如果有人修改数据而不考虑版本列,这将破坏乐观锁定的整个思想。

假设在一个电子商务应用程序中,用户想要下订单。这段代码将由多个线程执行。在悲观锁定中,当我们从DB中获得数据时,我们锁定它,这样其他线程就不能修改它了。我们处理数据,更新数据,然后提交数据。之后,我们释放锁。这里的锁定持续时间较长,我们从数据库记录开始锁定到提交。

In optimistic locking, we get the data and process the data without locking. So multiple threads can execute the code so far concurrently. This will speed up. While we update, we lock the data. We have to verify that no other thread updated that record. For example, If we had 100 items in inventory and we have to update it to 99 (because your code might be quantity=queantity-1) but if another thread already used 1 it should be 98. We had race condition here. In this case, we restart the thread so we execute the same code from the beginning. But this is an expensive operation, you already came to end but then restart. if we had a few race conditions, that would not be a big deal, If the race condition was high, there would be a lot of threads to restart. We might run in a loop. In the race condition is high, we should be using `pessimistic locking

乐观锁定的一个用例是让应用程序使用数据库允许其中一个线程/主机“声明”任务。这是一个经常为我派上用场的技巧。

我能想到的最好的例子是使用数据库实现的任务队列,多个线程同时声明任务。如果一个任务有状态'Available', 'Claimed', 'Completed', db查询可以这样说:Set status='Claimed' where status='Available'。如果多个线程试图以这种方式改变状态,那么除了第一个线程之外,其他线程都会因为脏数据而失败。

注意,这是一个只涉及乐观锁定的用例。因此,作为“乐观锁定用于不期望有太多冲突的情况”的替代说法,它也可以用于您期望有冲突但只希望一个事务成功的情况。

乐观假设你读的时候什么都不会改变。

悲观的人认为某件事会发生,所以锁定它。

如果数据被完全读取不是必要的,请使用乐观。你可能会得到奇怪的“肮脏”解读——但它不太可能导致死锁或类似的情况。

大多数web应用程序都可以接受脏读——在极少数情况下,下一次重新加载时数据不完全一致。

对于精确的数据操作(如在许多金融交易中)使用悲观。准确读取数据非常重要,没有未显示的更改——额外的锁定开销是值得的。

对了,Microsoft SQL server默认为页面锁定——基本上就是你正在读的那一行和两边的几行。行锁定更准确,但速度要慢得多。通常值得将事务设置为读提交或无锁,以避免读取时发生死锁。

乐观锁定意味着在读取一行时不使用排他锁,因此不会防止丢失更新或写倾斜。所以,使用乐观锁定:

如果没有发生丢失的更新或写倾斜。 或者,即使发生更新丢失或写倾斜也没有问题。

悲观锁定意味着在读取一行时使用排他锁定,从而防止丢失更新或写倾斜。所以,使用悲观锁定:

如果发生更新丢失或写倾斜。 或者出现丢失更新或写倾斜等问题。

在MySQL和PostgreSQL中,SELECT FOR UPDATE可以使用排他锁。

你可以检查我丢失更新的答案,并在MySQL中使用乐观锁定(不使用SELECT FOR update)和悲观锁定(使用SELECT FOR update)编写倾斜示例。