Mysql
防止並發插入導致的唯一約束衝突
我有一種情況,我需要在數據庫中插入一條唯一記錄:
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。(警告:多主拓撲需要更多程式碼。)