2011-09-17 25 views
2

我有這樣的情況下,在航空公司網站(使用Java)兩個獨立的客戶發送在同一時間兩個請求預訂相同的座位在同一航空公司從紐約到芝加哥
。我正在使用oracle數據庫,隔離級別被讀取提交。 這裏我的問題是oracle數據庫是否提供 任何解決方案來處理這種併發情況?我所知道的是,當第一個事務DML語句被觸發,將受影響 行獲得了鎖,將盡快提交完成和第二請求將繼續儘快 發佈關於印發回滾或commit.But當交易完成後,即首先完成並將覆蓋第一個。 所以它沒有幫助?在oracle數據庫中處理併發請求?

是在Java中,我可以對付使我的DB類爲單和使用方法上被執行更新synchronized關鍵字。 但是想知道是否有 無論如何,我們可以在數據庫級別本身這樣的問題?可能隔離級別作爲序列化可以幫助。但不確定?

回答

1

處理併發的網站上常見的做法是會對每一個可以讓你檢查它,因爲你得到了它一直沒有更新記錄的列。最後更新日期或順序版本號(由觸發器自動遞增)。

通常,你會讀出的數據(加上併發列)

SELECT seat,etc,version_no 
FROM t1 
WHERE column = a_value 

然後,當用戶最終獲得輪預訂座位,更新將工作,除非出現了更新。

(版本號或更新日期將在每次更新後更改)

BEGIN 
    UPDATE t1 
    SET seatTaken = true 
    WHERE seatid = ..... 
    AND version_no = p_version 
    RETURNING version_no INTO p_version; 
EXCEPTION WHEN NOT_FOUND THEN 
    --Generate a custom exception 
    --concurrency viloation the record has been updated already 
END; 

觸發自動更新的版本號應該是這樣

CREATE OR REPLACE TRIGGER t1_version 
AFTER INSERT OR UPDATE ON t1 
FOR EACH ROW 
BEGIN 
    IF :new.version_no IS NULL THEN 
     :new.version_no := 0; 
    ELSE 
     :new.version_no := :old.version_no + 1; 
    END IF; 
END; 
4

它只會在寫,如果你允許它。你可以嘗試像

UPDATE seatTable 
SET seatTaken = true 
WHERE .. find the seat, flight etc.. AND seatTaken = false 

這將返回1行更新後更新的第一時間,0行。

2

至於你提到,transanction一點設置將幫助您實現一項操作。執行這種限制的最好方法是確保您的關係模型在第一次成功時不會接受第二個操作。

而不必做就行了更新,更新說....座位=「取」,創建一個預約表(顧客,航班,座位),其具有約束(列:座椅=唯一)( lookup或者docs來學習創建表格的語法)。這樣,您的預訂過程將成爲預留表中的插入,您可以依靠RDBMS強制執行關係約束來保持您的業務模型的有效性。

例如讓T1是較早的運行時間,你必須:

t1=> insert into reservations(customer1,flight-x,seat-y) // succeeds. Customer 1 reserved the seat-y 
t2=> insert into reservations(customer2,flight-x,seat-y) // fails with RDBMS unique constrain violated. 

保留seat-y的唯一方法是再次先刪除以前的保留,這是你的業務流程要實現大概是什麼。

1

除了通過精心製作WHERE子句中單個UPDATE做的一切,你可以這樣做:

交易1:

  • SELECT ... FOR UPDATE完全鎖定的行中交易的持續時間。
  • 檢查該行的返回狀態是否爲「預訂」,如果是,退出(或重試另一行)。
  • UPDATE該行並將其「狀態」設置爲「已預訂」 - 確保沒有其他人在此期間更新它。
  • 提交。這消除了排他鎖。

事務2:

  • SELECT ... FOR UPDATE直到事務1結束,則排他鎖定的行。
  • 該行的返回狀態爲「預訂」(因爲事務1以此方式標記),因此退出(或可能重試另一行)。