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