多用戶併發環境下,「讀取-檢查-寫回」模式極易導致資料不一致。本文透過完整範例(卡片註冊系統),示範悲觀鎖(UPDLOCK/HOLDLOCK)與樂觀鎖(ROWVERSION/時間戳)的實作細節,並比較兩者適用場景與優缺點。
CREATE TABLE Card (
F_CardNO VARCHAR(20),
F_Name VARCHAR(20),
F_Flag BIT,
F_Time DATETIME
);
-- 插入 10 張未使用卡片
INSERT Card(F_CardNo, F_Flag) VALUES ('1111-1111',0), ... ('1111-1110',0);
在交易中使用 SELECT ... WITH (UPDLOCK, HOLDLOCK) 讀取目標列,持有更新鎖至交易結束,阻塞其他交易修改同一資料。適合衝突頻率高、等待可接受的場景。
表新增 ROWVERSION 欄位。更新時檢查版本號:UPDATE Card SET ..., Version = Version+1 WHERE F_CardNO=@id AND Version=@oldVersion。若影響行數為 0 則衝突,重試或報錯。適合衝突較少、追求高併發吞吐的場景。
SET LOCK_TIMEOUT 900000; -- 15 分鐘,避免無限期阻塞
合理選擇鎖策略,是高併發系統穩定運行的基石。