2017-03-10 70 views
0

您有以下兩列一個InnoDB表答:ID(PK),狀態MySQL的InnoDB的併發更新

兩個線程訪問以下順序表:

Thread 1: SELECT id from A where status = 0 LIMIT 1; 
Thread 2: SELECT id from A where status = 0 LIMIT 1; 

兩個線程選擇ID 1.

Thread 1: UPDATE A SET status = 1 WHERE id = 1 AND status = 0; 
Thread 2: UPDATE A SET status = 2 WHERE id = 1 AND status = 0; 

是否有可能兩個線程更新同一行?

現在增加交易:

Thread 1: SELECT id from A where status = 0 LIMIT 1; 
Thread 2: SELECT id from A where status = 0 LIMIT 1; 
Thread 1: START TRANSACTION; 
Thread 2: START TRANSACTION; 
Thread 1: UPDATE A SET status = 1 WHERE id = 1 AND status = 0; 
Thread 2: UPDATE A SET status = 2 WHERE id = 1 AND status = 0; 
Thread 1: COMMIT; 
Thread 2: COMMIT; 

是現在可能兩個線程將更新行?

在任何一種情況下,如果兩行都可以更新,那麼解決這個問題的正確方法是什麼?

+0

可能重複[如何處理數據庫中的併發更新?](http://stackoverflow.com/questions/1195858/how-to-deal-with-concurrent-updates-in-databases) –

回答

1

InnoDB默認鎖定機制是REPEATABLE_READ(見https://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-isolation-levels.html#isolevel_repeatable-read)。這意味着如果你在同一個索引上做兩次更新將以原子方式完成,但是我不相信你可以保證哪一次更新會先通過,而無需在你的程序中增加一些邏輯。 (第一次更新將由Thread首先獲取鎖來完成)。因此,要按照正確的順序管理更新,您需要實現程序中的邏輯(如果是Java,我會看看Barrier,LatchesSemaphores)。

+0

謝謝!我不太關心這個命令,我擔心只有其中的一個更新是可能的(因此,狀態= 0)。換句話說,在第一次更新之後,狀態值的變化對於獲取鎖的線程是否可見? – phenompbg

+0

好吧,那麼默認情況下兩個更新肯定是可能的 – Adonis

+0

是否將事務隔離改爲Serializable解決了這個問題? – phenompbg