首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Oracle 高併發訂票系統:LOCK TABLE SHARE MODE 實作與陷阱避坑

     編輯:Oracle 資料庫基礎

業務需求

飛機訂票等高併發場景,需確保座位數檢查與扣減的原子性,避免超賣。

正確實作模式

PROCEDURE book_ticket(...) IS
    v_cnt NUMBER;
    v_res VARCHAR2(50);
BEGIN
    -- 1. 共享鎖:允許並發讀,阻擋 DDL/全表獨佔鎖
    LOCK TABLE tb_book_ticket IN SHARE MODE;

    -- 2. 先插入訂單 (佔座)
    INSERT INTO tb_book_ticket (id, scheduled_flight, ticket_no, book_time)
    VALUES (seq_id.NEXTVAL, v_flight, v_ticket, SYSDATE);

    -- 3. 再統計該航班已訂數量
    SELECT COUNT(*) INTO v_cnt
    FROM tb_book_ticket
    WHERE scheduled_flight = v_flight;

    -- 4. 判斷是否超額
    IF v_cnt <= v_max_seats THEN
        v_res := 'book successfully';
        COMMIT;
    ELSE
        v_res := 'book unsuccessfully';
        ROLLBACK;  -- 釋放鎖並回滾插入
    END IF;
    RETURN v_res;
END;

兩大關鍵設計

要點錯誤做法正確做法
鎖模式EXCLUSIVE MODE (串行化,併發極低)SHARE MODE (並發讀,僅阻擋 DDL/獨佔)
檢查順序先 COUNT 再 INSERT先 INSERT 再 COUNT

為何必須「先 INSERT 再 COUNT」?

若先 COUNT,User A 讀到 99/100,User B 也讀到 99/100,兩者皆通過檢查並 INSERT → 變 101/100 超賣。
先 INSERT 讓該筆記錄對自身可見 (未提交也可見),COUNT 會包含自己剛插入的那筆,配合 SHARE MODE 序列化關鍵區段,確保準確。

替代方案提示

  • 細粒度鎖:SELECT ... FOR UPDATE SKIP LOCKED (11g+)
  • 應用層樂觀鎖:版本號/時間戳
  • 資料庫層:唯一索引 + 錯誤碼處理
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved