Mysql
MySQL 並發更新
假設我們在使用 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
釋放鎖