誤區 #26: SQL Server中存在真正的“事務嵌套”
錯誤
嵌套事務可不會像其語法表現的那樣看起來允許事務嵌套。我真不知道為什么有人會這樣寫代碼,我唯一能夠想到的就是某個哥們對SQL Server社區嗤之以鼻然后寫了這樣的代碼說:“玩玩你們”。
讓我更詳細的解釋一下,SQL Server允許你在一個事務中開啟嵌套另一個事務,SQL Server允許你提交這個嵌套事務,也允許你回滾這個事務。
但是,嵌套事務并不是真正的“嵌套”,對于嵌套事務來說SQL Server僅僅能夠識別外層的事務。嵌套事務是日志不正常增長的罪魁禍首之一因為開發人員以為回滾了內層事務,僅僅是回滾內層事務。
但實際上當回滾內層事務時,會回滾整個事務,而不是僅僅是內層。這也是為什么我說嵌套事務并不存在。
所以作為開發人員來講,永遠不要對事務進行嵌套。事務嵌套是邪惡的。
如果你不相信我說的,那么通過下面的例子就就會相信。創建完數據庫和表之后,每一條記錄都會導致日志增加8K。
復制代碼 代碼如下:
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
復制代碼 代碼如下:
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;
GO
復制代碼 代碼如下:
ROLLBACK TRAN InnerTran;
GO
復制代碼 代碼如下:
消息 6401,級別 16,狀態 1,第 2 行
無法回滾 InnerTran。找不到該名稱的事務或保存點。
復制代碼 代碼如下:
ROLLBACK TRAN;
GO
SELECT @@TRANCOUNT, COUNT (*) FROM t1;
GO
復制代碼 代碼如下:
BEGIN TRAN OuterTran;
GO
BEGIN TRAN InnerTran;
GO
INSERT INTO t1 DEFAULT Values;
GO 1000
COMMIT TRAN InnerTran;
GO
SELECT COUNT (*) FROM t1;
GO
復制代碼 代碼如下:
ROLLBACK TRAN OuterTran;
GO
SELECT COUNT (*) FROM t1;
GO
復制代碼 代碼如下:
BEGIN TRAN OuterTran;
GO
BEGIN TRAN InnerTran;
GO
INSERT INTO t1 DEFAULT Values;
GO 1000
DBCC SQLPERF ('LOGSPACE');
GO

復制代碼 代碼如下:
COMMIT TRAN InnerTran;
GO
CHECKPOINT;
GO
DBCC SQLPERF ('LOGSPACE');
GO

復制代碼 代碼如下:
COMMIT TRAN OuterTran;
GO
CHECKPOINT;
GO
DBCC SQLPERF ('LOGSPACE');
GO

新聞熱點
疑難解答