SQL Server中的事務(wù)簡(jiǎn)述
事務(wù)是單個(gè)工作單元。 如果某一事務(wù)成功,則在該事務(wù)中進(jìn)行的所有數(shù)據(jù)修改均會(huì)提交,成為數(shù)據(jù)庫(kù)中的永久組成部分。 如果事務(wù)遇到錯(cuò)誤且必須取消或回滾,則所有數(shù)據(jù)修改均被清除。
??SQL Server 以下列事務(wù)模式運(yùn)行。
- 自動(dòng)提交事務(wù):每條單獨(dú)的語(yǔ)句都是一個(gè)事務(wù)。
- 顯式事務(wù):每個(gè)事務(wù)均以 BEGIN TRANSACTION 語(yǔ)句顯式開始,以 COMMIT 或 ROLLBACK 語(yǔ)句顯式結(jié)束。
- 隱式事務(wù):在前一個(gè)事務(wù)完成時(shí)新事務(wù)隱式啟動(dòng),但每個(gè)事務(wù)仍以 COMMIT 或 ROLLBACK 語(yǔ)句顯式完成。
- 批處理級(jí)事務(wù):只能應(yīng)用于多個(gè)活動(dòng)結(jié)果集 (MARS),在 MARS 會(huì)話中啟動(dòng)的 Transact-SQL 顯式或隱式事務(wù)變?yōu)榕幚砑?jí)事務(wù)。 當(dāng)批處理完成時(shí)沒(méi)有提交或回滾的批處理級(jí)事務(wù)自動(dòng)由 SQL Server 進(jìn)行回滾。
事務(wù)語(yǔ)句
一個(gè)顯式事務(wù)可以由三個(gè)語(yǔ)句來(lái)描述,它們分別是開始事務(wù)、提交事務(wù)和回滾事務(wù)。
①開始事務(wù)
BEGIN { TRAN | TRANSACTION }
[{ transaction_name | @tran_name_variable }]
- transaction_name :分配給事務(wù)的名稱。
- @tran_name_variable:事務(wù)變量名。
②提交事務(wù)語(yǔ)句
COMMIT [{TRAN|TRANSACTION} [transaction_name|@tran_name_variable]] [WITH(DELAYED_DURABILITY = { OFF | ON })]
- DELAYED_DURABILITY:請(qǐng)求將此事務(wù)與延遲持續(xù)性一起提交的選項(xiàng)。 如果已用 DELAYED_DURABILITY = DISABLED 或 DELAYED_DURABILITY = FORCED 更改了數(shù)據(jù)庫(kù),則忽略該請(qǐng)求。
事務(wù)可以嵌套。當(dāng)在嵌套事務(wù)中使用時(shí),內(nèi)部事務(wù)的提交并不釋放資源或使其修改成永久修改。只有提交了外部事務(wù)時(shí),數(shù)據(jù)修改才具有永久性,而且資源才會(huì)被釋放。
??標(biāo)志一個(gè)成功的隱性事務(wù)或顯式事務(wù)的結(jié)束。 如果 @@TRANCOUNT為 1,所有的數(shù)據(jù)修改執(zhí)行,因?yàn)槭聞?wù)的數(shù)據(jù)庫(kù)的永久部分開始釋放由事務(wù)和 @ 遞減持有的資源的 COMMIT TRANSACTION ,從而使@TRANCOUNT為 0。 如果 @@TRANCOUNT大于 1,COMMIT TRANSACTION 遞減 @@TRANCOUNT只能由 1 和事務(wù)將保持活動(dòng)狀態(tài)。
③事務(wù)回滾語(yǔ)句
ROLLBACK { TRAN | TRANSACTION }
[ transaction_name | @tran_name_variable
| savepoint_name | @savepoint_variable ]
- savepoint_name:是savepoint_name從 SAVE TRANSACTION 語(yǔ)句。
- @savepoint_variable:是用戶定義的、包含有效保存點(diǎn)名稱的變量的名稱。
【備注】
??無(wú)savepoint_name或transaction_name的時(shí)候?qū)⒒貪L到事務(wù)開始。嵌套事務(wù)時(shí),該語(yǔ)句將所有內(nèi)層事務(wù)回滾到最外面的 BEGIN TRANSACTION 語(yǔ)句。
??在執(zhí)行 COMMIT TRANSACTION 語(yǔ)句后不能回滾事務(wù),但是 COMMIT TRANSACTION如果包含在要回滾的事務(wù)中的嵌套事務(wù)關(guān)聯(lián)時(shí)除外。 在這種情況下,也將回滾嵌套事務(wù),即使您對(duì)它發(fā)出了 COMMIT TRANSACTION。
??在事務(wù)內(nèi)允許有重復(fù)的保存點(diǎn)名稱,但如果 ROLLBACK TRANSACTION 使用重復(fù)的保存點(diǎn)名稱,則只回滾到最近的使用該保存點(diǎn)名稱的 SAVE TRANSACTION。
??在事務(wù)處理中,并不是所有T-SQL語(yǔ)句都可以通過(guò)回滾取消執(zhí)行的。例如創(chuàng)建/修改和刪除數(shù)據(jù)庫(kù)等對(duì)數(shù)據(jù)庫(kù)進(jìn)行的操作,對(duì)數(shù)據(jù)庫(kù)造成的影響是不能恢復(fù)的。因此,這些操作不能用于事務(wù)處理。
④設(shè)置事務(wù)保存點(diǎn)
SAVE { TRAN | TRANSACTION } { savepoint_name | @savepoint_variable }
用戶可以在事務(wù)內(nèi)設(shè)置保存點(diǎn)或標(biāo)記。 保存點(diǎn)可以定義在按條件取消某個(gè)事務(wù)的一部分后,該事務(wù)可以返回的一個(gè)位置。 如果將事務(wù)回滾到保存點(diǎn),則根據(jù)需要必須完成其他剩余的 Transact-SQL 語(yǔ)句和 COMMIT TRANSACTION 語(yǔ)句,或者必須通過(guò)將事務(wù)回滾到起始點(diǎn)完全取消事務(wù)。 若要取消整個(gè)事務(wù),使用窗體 ROLLBACK TRANSACTION transaction_name。 這將撤消事務(wù)的所有語(yǔ)句和過(guò)程。
??在事務(wù)中允許有重復(fù)的保存點(diǎn)名稱,但指定保存點(diǎn)名稱的 ROLLBACK TRANSACTION 語(yǔ)句只將事務(wù)回滾到使用該名稱的最近的 SAVE TRANSACTION。
??在使用 BEGIN DISTRIBUTED TRANSACTION 顯式啟動(dòng)或從本地事務(wù)升級(jí)的分布式事務(wù)中,不支持 SAVE TRANSACTION。
示例
A、提交嵌套事務(wù)
下面的示例創(chuàng)建一個(gè)表,生成三個(gè)級(jí)別的嵌套事務(wù),然后提交嵌套的事務(wù)。
CREATE TABLE TestTran (Cola int PRIMARY KEY, Colb char(3));
GO
-- This statement sets @@TRANCOUNT to 1.
BEGIN TRANSACTION OuterTran;
PRINT N'Transaction count after BEGIN OuterTran = '
+ CAST(@@TRANCOUNT AS nvarchar(10));
INSERT INTO TestTran VALUES (1, 'aaa');
-- This statement sets @@TRANCOUNT to 2.
BEGIN TRANSACTION Inner1;
PRINT N'Transaction count after BEGIN Inner1 = '
+ CAST(@@TRANCOUNT AS nvarchar(10));
INSERT INTO TestTran VALUES (2, 'bbb');
-- This statement sets @@TRANCOUNT to 3.
BEGIN TRANSACTION Inner2;
PRINT N'Transaction count after BEGIN Inner2 = '
+ CAST(@@TRANCOUNT AS nvarchar(10));
INSERT INTO TestTran VALUES (3, 'ccc');
-- This statement decrements @@TRANCOUNT to 2.
-- Nothing is committed.
COMMIT TRANSACTION Inner2;
PRINT N'Transaction count after COMMIT Inner2 = '
+ CAST(@@TRANCOUNT AS nvarchar(10));
-- This statement decrements @@TRANCOUNT to 1.
-- Nothing is committed.
COMMIT TRANSACTION Inner1;
PRINT N'Transaction count after COMMIT Inner1 = '
+ CAST(@@TRANCOUNT AS nvarchar(10));
-- This statement decrements @@TRANCOUNT to 0 and
-- commits outer transaction OuterTran.
COMMIT TRANSACTION OuterTran;
PRINT N'Transaction count after COMMIT OuterTran = '
+ CAST(@@TRANCOUNT AS nvarchar(10));