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

SQL Server Timestamp (Rowversion) 機制詳解:並發控制與增量同步實戰

     編輯:關於SqlServer

許多開發者誤以為 TIMESTAMP 是日期時間型別,實際上它是資料庫級遞增的二進位版本號(SQL Server 2012+ 建議用 ROWVERSION 同義字)。本文深入解析其運作原理、並發控制模式與增量同步應用。

一、核心觀念

  • 非時間:8 位元組二進位數字,與時鐘無關。
  • 資料庫級計數器:每次對含 ROWVERSION 資料表的 INSERT/UPDATE,計數器遞增並寫入該欄。
  • 每表僅一欄:一個資料表只能有一個 ROWVERSION 欄位。
  • 不可作主鍵:每次更新值都會改變,導致外鍵失效、索引維護成本高。
  • 取得目前值:SELECT @@DBTS 回傳目前資料庫最大 timestamp。

二、並發控制:樂觀鎖模式

場景:使用者 A、B 同時編輯同一筆資料,最後存檔者不應覆蓋先前變更。

資料表建立

CREATE TABLE dbo.Account (
    Id INT PRIMARY KEY,
    Balance DECIMAL(18,2),
    Ver ROWVERSION  -- 或 TIMESTAMP
);

更新邏輯(防止遺失更新)

-- 1. 讀取時同時取得 Ver
DECLARE @ver ROWVERSION;
SELECT @ver = Ver, Balance = 1000 FROM Account WHERE Id = 1;

-- 2. 業務邏輯運算...
-- 3. 更新時帶入原 Ver 做 WHERE 條件
UPDATE Account 
SET Balance = 900 
WHERE Id = 1 AND Ver = @ver;  -- 若 Ver 已被他人改變,ROWCOUNT = 0

IF @@ROWCOUNT = 0
    THROW 50001, '資料已被他人修改,請重新整理', 1;

三、增量資料同步(CDC 輕量替代方案)

需求:每小時將主庫異動同步至報表庫,不想用完整 CDC/Replication。

-- 1. 記錄上次同步最大 timestamp
CREATE TABLE SyncWatermark (TableName SYSNAME PRIMARY KEY, LastTs BINARY(8));
INSERT INTO SyncWatermark VALUES ('Account', 0x00000000000007D0);

-- 2. 同步查詢(只抓變更列)
DECLARE @last BINARY(8) = (SELECT LastTs FROM SyncWatermark WHERE TableName = 'Account');

SELECT Id, Balance, Ver
FROM Account
WHERE Ver > @last;  -- 二進位直接比較

-- 3. 同步完成後更新 watermark
UPDATE SyncWatermark 
SET LastTs = (SELECT MAX(Ver) FROM Account) 
WHERE TableName = 'Account';

四、實戰範例:模擬並發測試

-- 建立測試表
CREATE TABLE #Tmp (Val VARCHAR(10), Ver ROWVERSION);
INSERT INTO #Tmp (Val) VALUES ('abc');

-- 連線 1 (SSMS 視窗 1)
BEGIN TRAN;
DECLARE @rv ROWVERSION;
SELECT @rv = Ver FROM #Tmp WHERE Val = 'abc';
WAITFOR DELAY '00:00:05';  -- 模擬思考時間
UPDATE #Tmp SET Val = 'xyz' WHERE Ver = @rv;
COMMIT;

-- 連線 2 (SSMS 視窗 2,在 5 秒內執行)
DECLARE @rv ROWVERSION;
SELECT @rv = Ver FROM #Tmp WHERE Val = 'abc';
UPDATE #Tmp SET Val = 'aaa' WHERE Ver = @rv;  -- 此時 Ver 已被連線 1 更新,ROWCOUNT = 0

連線 2 更新失敗,成功避免「遺失更新」。

五、遷移建議

  • 新專案請直接使用 ROWVERSION 關鍵字,語意更清晰。
  • 舊系統 TIMESTAMP 可就地保留,功能完全相容。
  • 若需人類可讀的修改時間,請另加 DATETIME2 欄位搭配 DEFAULT SYSUTCDATETIME() + 觸發器更新。

掌握 ROWVERSION,即可輕鬆實現高效能樂觀鎖與輕量級增量同步,是分散式系統與高併發應用的基石工具。

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