【问题标题】:why execute part of the transaction when an error happens?为什么在发生错误时执行部分事务?
【发布时间】:2014-04-25 23:39:32
【问题描述】:

我有这笔交易:

BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT

BEGIN TRANSACTION

delete from Versions;
insert into Versions(Version) VALUES('1.0.0.0');
GO

ALTER TABLE dbo.MyTable ADD
    MyNewColumn varchar(1000) NULL

ALTER TABLE dbo.MyTable SET (LOCK_ESCALATION = TABLE)
GO
COMMIT

第一次版本表是空的,在 MyTable 中我有列“MyNewColumn”,所以当我尝试添加新列时出现错误。但是,当我执行脚本时,表格 Versions 有一条记录数据库的版本。

为什么?如果我正在使用事务并且我只有一个提交,那么我认为任何语句都不会在数据库中进行更改。

我希望如果其中一个语句失败,任何语句都不能更改数据库。

P.D.:我知道我可以在尝试添加之前检查该列是否存在,但我想知道为什么交易会像我预期的那样工作。

谢谢。

【问题讨论】:

  • 事务将执行所有操作,但直到最后才会提交。因此插入将插入一条未提交的记录,该记录将在您的事务范围内可见。如果您期望错误将代码包装在 try catch 块中并处理它们
  • 要补充 Tanner 所说的内容,您需要捕获错误并发出明确的 ROLLBACK。出现错误时事务不会自动回滚。你需要这样做。

标签: sql-server transactions batch-processing


【解决方案1】:

忽略设置位,您的脚本:

  • 开始交易
  • 删除
  • 插入
  • 运行一段代码会产生错误
  • 做一个COMMIT

因此,这些初始更改当然已应用。你可以设置XACT_ABORT,它会导致任何产生错误的batch回滚事务,但是你仍然需要非常小心:

create table T(ID int)
go
set xact_abort on
go
begin transaction
go
insert into T(ID) values (1)
go
alter table T add ID int null
go
insert into T(ID) values (2)
go
commit
go
select * from T

产生这些消息:

(1 row(s) affected)
Msg 2705, Level 16, State 4, Line 1
Column names in each table must be unique. Column name 'ID' in table 'T'
is specified more than once.

(1 row(s) affected)
Msg 3902, Level 16, State 1, Line 1
The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.

(1 row(s) affected)

并且表格中仍有一行包含2。为什么?因为错误通过回滚终止了事务,但是下一个批次(包含insert into T(ID) values (2))在没有显式事务存在的情况下运行。在批次的错误处理方面,除了一些手动步骤之外,您无法获得太多帮助,例如:

create table T(ID int)
go
set xact_abort on
go
begin transaction
go
insert into T(ID) values (1)
go
alter table T add ID int null
go
if @@TRANCOUNT = 0 goto errored
insert into T(ID) values (2)
errored:
go
if @@TRANCOUNT = 0 goto errored
commit
errored:
go
select * from T

而且您必须对可能出现错误的每个批次都执行相同操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 2016-03-18
    相关资源
    最近更新 更多