小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

別使用嵌套事務(wù)

 云端素館 2015-05-26

公司之前一直存在一個(gè)規(guī)范,就是禁止嵌套事務(wù)的使用,一直不太明白為什么,試了下應(yīng)該是無法控制回滾,今天看大牛的博客發(fā)現(xiàn),問題遠(yuǎn)遠(yuǎn)不只如此。

具體總結(jié)下來是以下3個(gè)問題

1、內(nèi)層事務(wù)回滾,只能回滾全部事務(wù),無法控制單一事務(wù)回滾

2、內(nèi)層事務(wù)提交后,回滾外層事務(wù),也會把內(nèi)層提交了的事務(wù)一起回滾

3、因?yàn)?的原因,只要整個(gè)事務(wù)不完全提交,日志空間都無法被釋放


    嵌套事務(wù)可不會像其語法表現(xiàn)的那樣看起來允許事務(wù)嵌套。我真不知道為什么有人會這樣寫代碼,我唯一能夠想到的就是某個(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í),會回滾整個(gè)內(nèi)層事務(wù),而不是僅僅是內(nèi)層。這也是為什么我說嵌套事務(wù)并不存在。

    所以作為開發(fā)人員來講,永遠(yuǎn)不要對事務(wù)進(jìn)行嵌套。事務(wù)嵌套是邪惡的。

    如果你不相信我說的,那么通過下面的例子就就會相信。創(chuàng)建完數(shù)據(jù)庫和表之后,每一條記錄都會導(dǎo)致日志增加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:回滾內(nèi)部事務(wù)時(shí)僅僅回滾內(nèi)部事務(wù)?

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

 

    你可以看到得出的結(jié)果是2和2000,下面我來回滾內(nèi)部的事務(wù),按照我們的猜想應(yīng)該只回滾1000條吧,但事實(shí)上你會得到如下結(jié)果:

ROLLBACK TRAN InnerTran;
GO

消息 6401,級別 16,狀態(tài) 1,第 2 行
無法回滾 InnerTran。找不到該名稱的事務(wù)或保存點(diǎn)。

 

    好吧,由Books Online來看,我只能使用外部事務(wù)的名稱或是將事務(wù)名稱留空來進(jìn)行回滾,代碼如下:

ROLLBACK TRAN;
GO

SELECT @@TRANCOUNT, COUNT (*) FROM t1;
GO

 

    現(xiàn)在我得到結(jié)果是0和0。正如Books Online所言,這個(gè)回滾操作將外部事務(wù)進(jìn)行了回滾并將全局變量@@TRANCOUNT設(shè)置為0。事務(wù)中所有的修改都被回滾,如果想部分回滾的話只能使用SAVE TRAN 和ROLLBACK TRAN。

   

測試 #2:嵌套事務(wù)中內(nèi)部事務(wù)提交后會保存內(nèi)部事務(wù)的修改嗎?

BEGIN TRAN OuterTran;
GO

BEGIN TRAN InnerTran;
GO

INSERT INTO t1 DEFAULT Values;
GO 1000

COMMIT TRAN InnerTran;
GO

SELECT COUNT (*) FROM t1;
GO

 

    正如我所期待,得到的結(jié)果是1000。這說明內(nèi)部事務(wù)提交是會修改到磁盤的。但是如果這時(shí)外部事務(wù)回滾的話,那么不應(yīng)該回滾內(nèi)部事務(wù)…

ROLLBACK TRAN OuterTran;
GO

SELECT COUNT (*) FROM t1;
GO

 

    但運(yùn)行上面查詢后結(jié)果是0,這說明外部事務(wù)的回滾會影響內(nèi)部事務(wù)。

 

測試 #3:提交嵌套的事務(wù)的內(nèi)部事務(wù)至少可以讓我清除日志吧。

   在開始這個(gè)測試之前我首先清除了日志,然后運(yùn)行如下代碼:

BEGIN TRAN OuterTran;
GO

BEGIN TRAN InnerTran;
GO

INSERT INTO t1 DEFAULT Values;
GO 1000

DBCC SQLPERF ('LOGSPACE');
GO

   得到結(jié)果:

    2012-10-24_105050

 

    下面我將事務(wù)提交后運(yùn)行CheckPoint(對于簡單恢復(fù)模式的數(shù)據(jù)庫將會截?cái)嗳罩?,得到的結(jié)果:

COMMIT TRAN InnerTran;
GO

CHECKPOINT;
GO

DBCC SQLPERF ('LOGSPACE');
GO

 

    2

 

    我們發(fā)現(xiàn)日志的使用不減反贈,這是由于日志寫入了CheckPoint記錄(詳情請看:How do checkpoints work and what gets logged)。提交內(nèi)部事務(wù)不會導(dǎo)致日志被清除,這是由于外部事務(wù)回滾時(shí)也會連同內(nèi)部事務(wù)一起回滾(譯者注:所以這部分VLF在外部事務(wù)提交之前永遠(yuǎn)不會被標(biāo)記位reusable)。所以這部分日志在外部事務(wù)提交之前永遠(yuǎn)不會被截?cái)?。為了證明這一點(diǎn),我提交外部事務(wù),然后再來看日志:

COMMIT TRAN OuterTran;
GO

CHECKPOINT;
GO

DBCC SQLPERF ('LOGSPACE');
GO

  3

 

    怎么樣,日志使用百分比大幅下降了吧。

    對于嵌套事務(wù)來說---Just Say no。(這句話你可以當(dāng)作來自SQLSkill.com的一個(gè)熱心的家伙給的福利微笑)


轉(zhuǎn)載地址: http://www.cnblogs.com/CareySon/archive/2013/01/22/2871204.html


    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多