2015-03-03 59 views
0

我創建了一個票務系統,它以最簡單的形式記錄一個加入隊列的用戶,並打印出一個包含隊列號的票。MySQL InnoDB插入和選擇鎖

當用戶按下一票,下面數據庫

INSERT details INTO All_Transactions_Table 
SELECT COUNT(*) as ticketNum FROM All_Transactions_Table WHERE date is TODAY 

這符合我不錯,在大多數情況下發生的。不過,我最近開始看到一些重複的門票號碼。即使在我自己多次運行Web服務後,我似乎也無法複製該問題。

我對它是如何發生的猜測是,在某些情況下INSERT只發生在之後SELECT COUNT。但是這是一個InnoDB表,我沒有使用INSERT DELAYED。 InnoDB有任何這樣的隱式機制嗎?

回答

1

我認爲你的問題是你有一個競爭條件。想象一下,你有兩個人來獲取門票。這裏的人之一:

INSERT details INTO All_Transactions_Table 

然後,前SELECT COUNT(*)可能發生,聯繫人的兩種走來並執行:

INSERT details INTO All_Transactions_Table 

現在,這兩個用戶獲得相同的票號。使用現有的代碼很難複製,因爲它取決於使用MySQL的線程的確切調度,這完全超出了您的控制範圍。

到這一點,最好的解決辦法是使用某種AUTO_INCREMENT一欄,提供票號,但做不到這一點,你也許可以用交易來達到你想要什麼:

START TRANSACTION 
SELECT COUNT(*) + 1 as ticketNum FROM All_Transactions_Table WHERE date is TODAY FOR UPDATE 
INSERT details INTO All_Transactions_Table 
COMMIT 

然而,是否不是這個工作將取決於你設置了什麼事務隔離級別,並且它不會非常有效。