2017-03-08 108 views
1

我有以下表格:Tour,Customer,TourCustomerXRef。假設每個巡迴賽都有容量上限。現在請求到達後臺進行預訂。如果滿足條件,則選擇並檢查並插入

我需要做的是:

  1. SELECT和count()所有在TourCustomerXRef在tourid = 123
  2. 在程序代碼中的條目(或查詢):如果count( )<第
  3. 真: INSERT成TourCustomerXRef,返回成功
  4. 題:返回一個錯誤

但是,可能後端api被同時調用。這可能導致SELECT語句在最大值下返回一個數字。容量兩次,導致INSERT被執行多次(即使只剩下一個地方)。

以上情況最好的預防措施是什麼?設置事務隔離級別可序列化?或可重複讀?

我擔心應用程序邏輯(儘管它只是一個簡單的if)可能會損害性能,因爲讀寫鎖不會允許api執行查詢,只是想選擇數據而不插入任何內容,對?

(使用MariaDB的)

+0

聽起來像是你想有一個觸發器。這種檢查不應該在應用程序級別完成。 –

+0

@GordonLinoff觸發器在我的情況下會做什麼?我很遺憾不能在插入 – petul

回答

2

您可以嘗試在SELECT(MySQL的例子)使用鎖提示 「FOR UPDATE」:

BEGIN TRANSACTION; 
SELECT * FROM TourCustomerXRef FOR UPDATE WHERE ...; 
INSERT ...; 
COMMIT; 
+0

之前拿出一些不需要選擇檢查的東西,這很好,謝謝。 – petul

+0

快速提問,例如tourcustomerxref中沒有條目時,例如tourid = 1,並且我使用SELECT FOR UPDATE爲tourid = 1運行兩個事務,兩者都可以選擇。然而,在插入時,其中一個阻塞,直到另一個提交。這導致一個事務(第一個)成功,另一個返回'錯誤1213(40001):嘗試獲取鎖定時發現的死鎖;'這是不可避免的權利? – petul

+0

一些死鎖是不可避免的。 (沒有足夠的細節來說明這一點)。因此,計劃在發生死鎖時重新運行事務 –