我們可以把SSIS中的整個(gè)package包含在一個(gè)事務(wù)中,但是如果在package的執(zhí)行過(guò)程中有一個(gè)表需要鎖定應(yīng)該怎么處理呢?SSIS內(nèi)建的事務(wù)處理可以解決這個(gè)問(wèn)題。在此之前首先來(lái)熟悉一下SQL Server中的事務(wù)的概念。
事務(wù)
SQL Server中的事務(wù)是單個(gè)的工作單元。如果某一事務(wù)成功,則在該事務(wù)中進(jìn)行的所有數(shù)據(jù)修改均會(huì)提交,成為數(shù)據(jù)庫(kù)中永久的組成部分。如果事務(wù)遇到錯(cuò)誤且必須取消或回滾,則所有的數(shù)據(jù)修改均被清除。
在SQL Server中使用事務(wù)有可能會(huì)造成一些預(yù)想不到的結(jié)果,具體來(lái)說(shuō)有臟讀,不可重復(fù)讀和幻讀三種結(jié)果。
在SQL Server中給事務(wù)指定一個(gè)隔離級(jí)別,這個(gè)隔離級(jí)別定義該事務(wù)與其他事務(wù)進(jìn)行資源或數(shù)據(jù)更改相隔離的級(jí)別。事務(wù)隔離級(jí)別決定了是否鎖定SQL Server對(duì)象,下面是SQL Server中的事務(wù)隔離級(jí)別。
還有兩種是SQL Server 2005中新添加的事務(wù)隔離級(jí)別
所有上述的事務(wù)處理都在tempdb數(shù)據(jù)庫(kù)中一個(gè)類似版本庫(kù)的數(shù)據(jù)對(duì)象中自動(dòng)進(jìn)行,當(dāng)遇到更新未被提交的情況,數(shù)據(jù)引擎會(huì)檢索這個(gè)版本庫(kù)得到合適的提交結(jié)果。維護(hù)這個(gè)版本庫(kù)的工作由SQL Server自動(dòng)進(jìn)行,不需要人為干預(yù)。
SSIS中的事務(wù)處理
SSIS中的包,容器(例如Loop,F(xiàn)oreach Loop,Sequence)或者一個(gè)單獨(dú)的任務(wù)中都可以設(shè)置事務(wù)處理選項(xiàng)。事務(wù)處理選項(xiàng)有下面一些值
內(nèi)建的事務(wù)處理要使用Distributed Transaction Coordinator(MSDTC)服務(wù),這個(gè)服務(wù)必須開(kāi)啟。MSDTC允許使用分布式事務(wù)處理,例如在一個(gè)事務(wù)中同時(shí)處理SQL Server數(shù)據(jù)庫(kù)和Oracle數(shù)據(jù)庫(kù)。如果沒(méi)有開(kāi)啟這個(gè)服務(wù)會(huì)得到下面的錯(cuò)誤提示.
Error: 0xC001401A at Transaction: The SSIS Runtime has failed to start the distributed transaction due to error 0x8004D01B "The Transaction Manager is not available.". The DTC transaction failed to start. This could occur because the MSDTC Service is not running.
注意SSIS中包中的元素的事務(wù)隔離級(jí)別是Serializable,這種級(jí)別會(huì)影響鎖的持續(xù)時(shí)間。下面我們來(lái)用一個(gè)例子說(shuō)明在如何package中鎖定一個(gè)表
1/*命名*/
2Create TranQueue Table
3/*SQLstatement設(shè)置*/
4IF NOT EXISTS ( SELECT * FROM sys.objects WHERE object_id =
5
6OBJECT_ID(N'dbo.TranQueue') AND type in (N'U') )
7BEGIN
8execute('CREATE TABLE dbo.TranQueue(message nvarchar(256))')
9END
10/*命名*/
11Populate TranQueue
12/*SQLstatement設(shè)置*/
13INSERT INTO dbo.TranQueue VALUES ('Test Message' + CONVERT
14
15(NVARCHAR(23), GETDATE(), 121))
16/*命名*/
17Create TranQueueHistory table
18/*SQLstatement設(shè)置*/
19IF NOT EXISTS ( SELECT * FROM sys.objects WHERE object_id =
20
21OBJECT_ID(N'dbo.TranQueueHistory') AND type in (N'U') )
22BEGIN
23execute('CREATE TABLE dbo.TranQueueHistory(message nvarchar(256))')
24END
1DELETE TOP(10) dbo.TranQueue
2OUTPUT DELETED.*
3INTO dbo.TranQueueHistory
4FROM dbo.TranQueue WITH (TABLOCKX)
圖1
10.打開(kāi)SQL Server Management Studion,選擇對(duì)應(yīng)的數(shù)據(jù)庫(kù),新建一個(gè)Query,執(zhí)行下面的語(yǔ)句,NOLOCK選項(xiàng)忽略鎖,這個(gè)語(yǔ)句查詢得到一條記錄 Message2011-04-10 14:22:31.043,但是這條記錄并沒(méi)有提交
1SELECT * FROM dbo.TranQueueHistory WITH (NOLOCK)
11.執(zhí)行下面的語(yǔ)句
1SELECT * FROM dbo.TranQueue
語(yǔ)句將阻塞在這里,語(yǔ)句一直停留在執(zhí)行狀態(tài),不會(huì)結(jié)束。因?yàn)樵赑rocess TranQueue任務(wù)中我們使用TABLOCKX,在這里將等待任務(wù)回滾或者提交?;蛘呖梢詫?xiě)成這樣,它任然會(huì)阻塞
1 DELETE TOP(10) dbo.TranQueue
2 INSERT INTO dbo.TranQueueHistory VALUES ('Test Message' + CONVERT(NVARCHAR(23), GETDATE(), 121))
12. 點(diǎn)擊Continue按鈕或者Debuge按鈕,會(huì)看到package執(zhí)行失敗,執(zhí)行SELECT * FROM dbo.TranQueueHistory
WITH (NOLOCK);因?yàn)閳?zhí)行了回滾,不會(huì)得到任何結(jié)果。SELECT * FROM dbo.TranQueue,任然有一條記錄。
SELECT * FROM dbo.TranQueueHistory WITH (NOLOCK)
NOLOCK提示忽略鎖,這個(gè)語(yǔ)句查詢得到一條記錄 Message2011-04-10 14:22:31.043,但是這條記錄并沒(méi)有提交
13. 執(zhí)行下面的語(yǔ)句,
SELECT * FROM dbo.TranQueue
sql語(yǔ)句將阻塞在這里,語(yǔ)句一直執(zhí)行。因?yàn)樵赑rocess TranQueue任務(wù)中我們使用TABLOCKX,在這里將等待任務(wù)回滾或者提交?;蛘呖梢詫?xiě)成這樣
DELETE TOP(10) dbo.TranQueue;INSERT INTO dbo.TranQueueHistory VALUES ('Test Message' + CONVERT(NVARCHAR(23), GETDATE(), 121)),它任然會(huì)阻塞
14. 點(diǎn)擊Continue按鈕或者Debuge按鈕,會(huì)看到package執(zhí)行失敗,執(zhí)行SELECT * FROM dbo.TranQueueHistory WITH (NOLOCK);因?yàn)閳?zhí)行了回滾,不會(huì)得到任何結(jié)果。執(zhí)行SELECT * FROM dbo.TranQueue,任然有一條記錄。
如果設(shè)置變量User::v_SimulateFailure的值為0,不會(huì)執(zhí)行Simulate Failure任務(wù),就不會(huì)回滾,TranQueue中的記錄會(huì)被寫(xiě)入到TranQueueHistory中。這里有一個(gè)很有意思的語(yǔ)句:
DELETE TOP(10) dbo.TranQueue
OUTPUT DELETED.*
INTO dbo.TranQueueHistory
FROM dbo.TranQueue WITH (TABLOCKX)
如果兩個(gè)表的結(jié)構(gòu)有一部分是是一樣的,現(xiàn)在想把一個(gè)表的數(shù)據(jù)導(dǎo)入到另外一個(gè)表中,可以使用DELETE SourceTable OUTPUT DELETE.*/DELETE.Column1,DELETE.Column2... INTO DestinationTable FROM SourceTable,這樣第一個(gè)表中的數(shù)據(jù)會(huì)被“剪切”到第二個(gè)表中。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注