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

OLTP 環境下大交易引發阻塞的演進與解決之道

     編輯:關於SqlServer

在高併發 OLTP 系統中,**大交易** 是阻塞風暴的核心推手。本文透過實戰案例,展示大交易如何從「保護資料一致性」演變為「系統癱瘓元兇」,並提供漸進式解決方案:快取緩衝 → 拆解交易 → 公私資料分離 → 最終一致性模式。

案例背景

-- 交易 1: 業務核心大交易 (低頻但耗時)
BEGIN TRAN
    INSERT INTO Message (Id, Col1, Col2...) VALUES (@Id, @Col1, @Col2...);  -- 私有資料
    UPDATE Thread SET Post_Count = NVL(Post_Count,0) + 1 WHERE Id = @V_Id;   -- 公開熱點資料
    UPDATE Test_User SET Sum_Reply = Sum_Reply + 1 WHERE UserId = @V_UserId; -- 私有資料
COMMIT TRAN

-- 交易 2: 高頻熱點更新 (極高頻)
UPDATE Thread SET View_Count = NVL(View_Count,0) + 1 WHERE Id = @V_Id;

演進階段與對策

階段 1:業務初期 — 無感知

  • 低併發、小資料量,大交易執行快,鎖持有時間短,無阻塞

階段 2:併發增長 — 交易 1 阻塞 交易 2

  • 現象: 交易 1 持有 Thread 表鎖 (X 鎖) 期間,大量交易 2 等待 → LCK_M_X 等待激增、回應時間飆升
  • 對策:快取緩衝 — 交易 2 的 View_Count 更新改為 Redis 計數器,定期 (如每 5 分鐘) 批次回寫 DB,降低 DB 寫入頻率 99%+

階段 3:高併發成熟期 — 交易 1 自我阻塞

  • 現象: 交易 1 本身頻率提高,多個交易 1 同時更新同一 Thread 列 → 互相阻塞、死鎖風險
  • 極端拆解 (反模式): 完全拆分為 3 個獨立交易 → **資料不一致風險極高** (伺服器宕機/應用異常導致部分提交)

階段 4:公私資料分離 — 折衷最佳解

分析交易 1 三條語句的資料特性:

語句資料屬性阻塞風險歸類
INSERT Message新增單筆,無衝突無私有
UPDATE Thread.Post_Count熱點列,高併發更新極高公開
UPDATE Test_User.Sum_Reply按 UserId 更新,用戶隔離低私有

重構方案:

-- 交易 1_1: 公開熱點資料獨立交易 (極短、極快)
BEGIN TRAN
    UPDATE Thread SET Post_Count = NVL(Post_Count,0) + 1 WHERE Id = @V_Id;
COMMIT TRAN

-- 交易 1_2: 私有資料合併交易 (較長但無衝突)
BEGIN TRAN
    INSERT INTO Message (Id, Col1, Col2...) VALUES (@Id, @Col1, @Col2...);
    UPDATE Test_User SET Sum_Reply = Sum_Reply + 1 WHERE UserId = @V_UserId;
COMMIT TRAN

效果評估

指標原大交易拆解後改善
Thread 表鎖持有時間~50-200ms (含 INSERT/UPDATE User)~1-5ms (僅 UPDATE Thread)95%+ 降低
交易 1 自我阻塞概率高極低消除熱點競爭
資料一致性風險強一致 (ACID)最終一致 (Message/User 可能比 Thread 晚可見)業務可接受 (計數器延遲秒級)
應用複雜度低中 (需處理兩階段提交邏輯)可控

進階模式:最終一致性與補償機制

若業務**嚴格要求強一致** (如金融帳務),可採用:

  1. Saga 模式: 每步驟有對應補償交易,失敗時反向執行補償
  2. 異步事件驅動: 交易 1 提交後發送事件 (Service Broker/Kafka/RabbitMQ),消費者異步更新 Thread/View_Count,失敗重試 + 死信隊列告警
  3. 樂觀併發控制: Thread 表加 Version 欄位,UPDATE ... SET Count=Count+1, Version=Version+1 WHERE Id=@Id AND Version=@OldVer,失敗則重讀重試

核心原則總結

  1. 識別熱點: 區分「公開熱點資料」與「私有隔離資料」
  2. 隔離熱點: 熱點更新獨立為極短交易,或移出關係資料庫 (Redis/Counter Service)
  3. 縮小交易: 單一職責原則,一個交易只做一件「有衝突風險」的事
  4. 接受最終一致: 非核心計數器、統計欄位允許秒級延遲,換取系統吞吐量
  5. 補償機制: 異步流程必須有重試、冪等、死信、人工介入完整閉環

大交易不是洪水猛獸,**關鍵在於識別其內部的衝突域並加以隔離**。將這套分析框架納入架構評審清單,讓 OLTP 系統在高併發下穩健演進。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved