Mysql

MySQL 並發更新

  • April 23, 2022

假設我們在使用 MySQL的應用程序中有以下情況,其中使用者可以購買商品,並且每個商品都有一個買家,但商品的價格可能會發生變化。

虛擬碼:

BEGIN TRANSACTION

seenPrice = SELECT price FROM Item
   WHERE id = ABC AND buyer IS NULL

UPDATE Item SET buyer = X
   WHERE id = ABC AND buyer IS NULL AND price = seenPrice

COMMIT

UPDATE 語句中的seenPrice變數和buyer IS NULL AND price = seenPrice檢查用作樂觀鎖,以確保不會出現任何並發問題。

在多執行緒環境中,執行緒 A 和執行緒 B 同時通過SELECT語句並說執行緒 A 先執行UPDATE語句,然後並發性不是問題**,但 A 和 B 是否有可能同時執行UPDATE語句相同的確切時間?**對於上下文,正在使用 Spring Boot 和 Spring Data JPA 開發應用程序。

A和B是否有可能同時執行該UPDATE語句?

這些語句可能會同時開始執行,但它們不能同時更新同一行。更新語句必須先獲取行上的排他鎖才能修改,而鎖獲取是嚴格序列化的原子操作,意味著其中一個並發會話總是先獲取鎖,其他會話會被阻塞.

鎖獲取始終是原子的,無論 DBMS 或儲存引擎如何——如果不是,它作為並發控制機制將完全無用。

鎖定機制並不關心您的應用程序是使用樂觀還是悲觀鎖定方法編寫的——改變的是鎖定的時間。使用悲觀鎖定,您希望有很多並發活動,並且您希望確保您的事務成功(以防止並發更新為代價):

應用數據庫
SELECT ... FOR UPDATE獲取鎖
做點別的
UPDATE ...
COMMIT釋放鎖

使用樂觀鎖定,您不會期望有太多的並發活動,因此您的應用程序無法完成更新的可能性很低,並且您不會長時間保持鎖定:

應用數據庫
SELECT ...
做點別的
UPDATE ...獲取鎖
COMMIT釋放鎖

引用自:https://dba.stackexchange.com/questions/311242