Mysql

防止並發插入導致的唯一約束衝突

  • September 22, 2020

我有一種情況,我需要在數據庫中插入一條唯一記錄:

  • SELECT user FROM users WHERE id = 'some_randomly_generated_id'
  • 如果user不存在,INSERT INTO users WHERE id = 'some_randomly_generated_id'

問題是,可以在SELECT查詢之後但在查詢之前添加匹配記錄INSERT,從而導致唯一約束錯誤。我將如何防止/解決這個問題?這些是我經過一些研究後目前的想法:

  • 在事務下執行這些查詢並使用SELECT user FROM users WHERE ... FOR SHARE鎖定行,因此不能插入新記錄(我可能錯了,請糾正我)。
  • 處理應用程序中的唯一約束錯誤,假裝記錄插入成功。(沒有事務,可能會更好,因為它允許更大的並發性並且實現起來很簡單)
  • 只執行INSERT IGNORE查詢,它會默默地忽略唯一約束錯誤。(在我看來類似於第二種方法,只是應用程序中沒有處理錯誤)。

提前致謝。我的方言是 MySQL,隔離級別是REPEATABLE READS如果這有助於更容易回答這個問題。

未能包裝交易會導致您的問題。

do
   compute random number
   BEGIN;
   SELECT ... FOR UPDATE;
   if row exists, then start loop over
   INSERT ...;
   COMMIT;
until success

並且不用擔心事務隔離模式。

或者…

do
   compute random number
   INSERT ...;
until success

autocommit = ON; 不用擔心隔離模式。

或者…使用AUTO_INCREMENT列——MySQL 每次都會處理保證一個唯一的 id。(警告:多主拓撲需要更多程式碼。)

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