在很多编程语言中,可以实现嵌套,但在TSQL中,可以实现嵌套事务吗?
答案:不可以
虽然我们可以写如下code:
CREATE TABLE #TB1
(
ID INT
)
--创建事务1
BEGIN TRAN TR1
INSERT INTO #TB1
SELECT 1
--在事务1中创建事务2
BEGIN TRAN TR2
INSERT INTO #TB1
SELECT 2
--回滚事务
ROLLBACK TRAN
SELECT * FROM #TB1
DROP TABLE #TB1
以上代码能够正常运行,且事务1和事务2都被回滚,看似实现了嵌套事务,但是我们在事务1中,不能指定回滚事务2,以下代码会出错:
CREATE TABLE #TB1
(
ID INT
)
--创建事务1
BEGIN TRAN TR1
INSERT INTO #TB1
SELECT 1
--在事务1中创建事务2
BEGIN TRAN TR2
INSERT INTO #TB1
SELECT 2
--尝试回滚事务2
ROLLBACK TRAN TR2
--在尝试提交事务1
COMMIT TRAN TR1
SELECT * FROM #TB1
DROP TABLE #TB1
以上错误是对事务的一种错误认识,以其他编程的思想去编写TSQL,我们知道事务可以提交和回滚,所以我们尝试用嵌套事务来实现部分回滚,其实我们只需要一个事务,并在最终决定提交事务还是回滚事务,在事务中,如果需要部分回滚,我们只需使用事务保存点便可以实现:
CREATE TABLE #TB1
(
ID INT
)
--创建事务1
BEGIN TRAN TR1
INSERT INTO #TB1
SELECT 1
--创建事务保存点1
SAVE TRAN savepoint1
INSERT INTO #TB1
SELECT 2
--将事务回滚到事务检查点1之前
ROLLBACK TRAN savepoint1
COMMIT TRAN TR1
SELECT * FROM #TB1
DROP TABLE #TB1
结论:
1.可以在一个事务中创建一个新的事务,但无法使之嵌套,即内层事务相对于外层事务而言独立存在,任何回滚都将回滚所有事务,且这些“嵌套”事务间无隔离性。
2.要想在事务里进行部分回滚,可以使用事务保存点来实现。