SQL Server誤區30日談 第26天 SQL Server中存在真實的“事務嵌套”。本站提示廣大學習愛好者:(SQL Server誤區30日談 第26天 SQL Server中存在真實的“事務嵌套”)文章只能為提供參考,不一定能成為您想要的結果。以下是SQL Server誤區30日談 第26天 SQL Server中存在真實的“事務嵌套”正文
誤區 #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
測試 #1:回滾外部事務時僅僅回滾外部事務?
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
你可以看到得出的成果是2和2000,上面我往返滾外部的事務,依照我們的料想應當只回滾1000條吧,但現實上你會獲得以下成果:
ROLLBACK TRAN InnerTran;
GO
新聞 6401,級別 16,狀況 1,第 2 行
沒法回滾 InnerTran。找不到該稱號的事務或保留點。
好吧,由Books Online來看,我只能應用內部事務的稱號或是將事務稱號留空來停止回滾,代碼以下:
ROLLBACK TRAN;
GO
SELECT @@TRANCOUNT, COUNT (*) FROM t1;
GO
如今我獲得成果是0和0。正如Books Online所言,這個回滾操作將內部事務停止了回滾並將全局變量@@TRANCOUNT設置為0。事務中一切的修正都被回滾,假如想部門回滾的話只能應用SAVE TRAN 和ROLLBACK TRAN。
測試 #2:嵌套事務中外部事務提交後會保留外部事務的修正嗎?
BEGIN TRAN OuterTran;
GO
BEGIN TRAN InnerTran;
GO
INSERT INTO t1 DEFAULT Values;
GO 1000
COMMIT TRAN InnerTran;
GO
SELECT COUNT (*) FROM t1;
GO
正如我所等待,獲得的成果是1000。這解釋外部事務提交是會修正到磁盤的。然則假如這時候內部事務回滾的話,那末不該該回滾外部事務…
ROLLBACK TRAN OuterTran;
GO
SELECT COUNT (*) FROM t1;
GO
但運轉下面查詢後成果是0,這解釋內部事務的回滾會影響外部事務。
測試 #3:提交嵌套的事務的外部事務至多可讓我消除日記吧。
在開端這個測試之前我起首消除了日記,然後運轉以下代碼:
BEGIN TRAN OuterTran;
GO
BEGIN TRAN InnerTran;
GO
INSERT INTO t1 DEFAULT Values;
GO 1000
DBCC SQLPERF ('LOGSPACE');
GO
獲得成果:
上面我將事務提交後運轉CheckPoint(關於簡略恢復形式的數據庫將會截斷日記),獲得的成果:
COMMIT TRAN InnerTran;
GO
CHECKPOINT;
GO
DBCC SQLPERF ('LOGSPACE');
GO
我們發明日記的應用不減反贈,這是因為日記寫入了CheckPoint記載(概況請看:How do checkpoints work and what gets logged)。提交外部事務不會招致日記被消除,這是因為內部事務回滾時也會連同外部事務一路回滾(譯者注:所以這部門VLF在內部事務提交之前永久不會被標志位reusable)。所以這部門日記在內部事務提交之前永久不會被截斷。為了證實這一點,我提交內部事務,然後再來看日記:
COMMIT TRAN OuterTran;
GO
CHECKPOINT;
GO
DBCC SQLPERF ('LOGSPACE');
GO
麼樣,日記應用百分比年夜幅降低了吧。
關於嵌套事務來講---Just Say no。(這句話你可以看成來自SQLSkill.com的一個熱情的家伙給的福利:-)