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

SQL Server 不存在真正的「交易巢狀」:ROLLBACK 內層實際回滾整個外層交易

     編輯:關於SqlServer

核心觀念

SQL Server 的巢狀交易不是真正的巢狀。語法雖允許 BEGIN TRAN 巢狀、COMMIT 內層、ROLLBACK 內層,但引擎僅識別最外層交易。@@TRANCOUNT 只是計數器,不代表獨立交易上下文。

實測證明

CREATE DATABASE NestedXactsAreNotReal;
GO
USE NestedXactsAreNotReal;
GO
ALTER DATABASE NestedXactsAreNotReal SET RECOVERY SIMPLE;
GO
CREATE TABLE t1 (c1 INT IDENTITY, c2 CHAR(8000) DEFAULT 'a');
CREATE CLUSTERED INDEX t1c1 ON t1(c1);
GO
SET NOCOUNT ON;
GO

-- 測試:外層插入 1000 列,內層插入 1000 列
BEGIN TRAN OuterTran;
GO
INSERT INTO t1 DEFAULT VALUES;
GO 1000
BEGIN TRAN InnerTran;
GO
INSERT INTO t1 DEFAULT VALUES;
GO 1000
SELECT @@TRANCOUNT, COUNT(*) FROM t1; -- 結果:2, 2000
GO

-- 嘗試只回滾內層
ROLLBACK TRAN InnerTran;
GO
-- 錯誤 6401:找不到該名稱的交易或儲存點。

-- 正確語法:ROLLBACK TRAN(無名稱)或 ROLLBACK TRAN OuterTran
ROLLBACK TRAN;
GO
SELECT @@TRANCOUNT, COUNT(*) FROM t1; -- 結果:0, 0(全部回滾)

關鍵行為

  • COMMIT 內層:僅遞減 @@TRANCOUNT,不寫入磁碟,資料仍可被外層 ROLLBACK 回滾。
  • ROLLBACK 內層(無名稱或外層名稱):回滾整個外層交易,將 @@TRANCOUNT 歸零。
  • 若需部分回滾,必須使用 SAVE TRAN savepoint_name 與 ROLLBACK TRAN savepoint_name。

開發建議

永遠不要在程式碼中使用巢狀交易。 它是記錄異常增長、鎖定時間過長、邏輯錯誤的常見根因。若需模組化交易控制,請在單一交易內使用儲存點,或重構為扁平化交易邊界。

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