SQL Server中存在真正的“事務巢狀”
本系列文章是我在sqlskill.com的PAUL的部落格看到的,很多誤區都比較具有典型性和代表性,原文來自T-SQL Tuesday #11: Misconceptions about.... EVERYTHING!!,經過我們團隊的翻譯和整理釋出在AgileSharp上。希望對大家有所幫助。
誤區 #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的一個熱心的傢伙給的福利
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/430/viewspace-2806185/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- sql server中巢狀事務*SQLServer巢狀
- golang的巢狀事務管理Golang巢狀
- 關於 MySQL 的巢狀事務MySql巢狀
- Oracle 巢狀事務 VS 自治事務Oracle巢狀
- Laravel 之巢狀事務 transactions 實現Laravel巢狀
- java spring巢狀事務詳情和事務傳播型別JavaSpring巢狀型別
- 對比SQL中簡單巢狀查詢與非巢狀查詢CFSQL巢狀
- Spring中事務巢狀這麼用一定得注意了!!Spring巢狀
- Locust 任務巢狀巢狀
- 瞭解SQL Server觸發器及觸發器中的事務AWSQLServer觸發器
- Vue中的巢狀路由Vue巢狀路由
- SQL Server的巢狀儲存過程中使用同名的臨時表怪像淺析SQLServer巢狀儲存過程
- JavaScript中if巢狀assert的方法JavaScript巢狀
- SQL Server中事務日誌自動增長對效能的影響(下)PGSQLServer
- SQL Server中事務日誌自動增長對效能的影響(上)OSSQLServer
- java定時任務巢狀Java巢狀
- 監控 SQL Server 的執行狀況SQLServer
- Linux的中斷可以巢狀嗎?Linux巢狀
- SQL事務SQL
- repeater中巢狀放入RadioButtonList巢狀
- MS SQL Server資料庫事務鎖機制分析(轉)SQLServer資料庫
- iOS block巢狀block中weakify的使用iOSBloC巢狀
- SQL Server 表的管理_關於事務操作的詳解(案例程式碼)SQLServer
- SQL Server 2008中Analysis Services的新特性——深入SQL Server 2008SQLServer
- SQL--事務SQL
- 在SQL Server上測試事務日誌的自動增長(三)QOSQLServer
- 在SQL Server上測試事務日誌的自動增長(二)TGSQLServer
- 在SQL Server上測試事務日誌的自動增長(一)JPSQLServer
- js中的函式巢狀和閉包JS函式巢狀
- SQL Server 中的 ACID 屬性SQLServer
- SQL Server 表分割槽注意事項HXSQLServer
- Sql Server 資料庫事務與鎖,同一事務更新又查詢鎖?期望大家來解惑SQLServer資料庫
- Oracle Gateway for SQL Server時2PC分散式事務異常處理OracleGatewaySQLServer分散式
- html的巢狀規則HTML巢狀
- 減少程式碼中該死的 if else 巢狀巢狀
- setTimeout和箭頭函式巢狀中的this指向函式巢狀
- HTML中div巢狀div的margin不起作用HTML巢狀
- 【java】【集合】去除ArrayList中的元素、ArrayList巢狀ArrayListJava巢狀