【问题标题】:SQL Server : BEGIN TRAN ... COMMIT without ROLLBACK does not rollback depending on the errorSQL Server : BEGIN TRAN ... COMMIT without ROLLBACK 不会根据错误回滚
【发布时间】:2018-10-31 08:00:51
【问题描述】:

在 Microsoft SQL Server 中,我创建了一个测试表

CREATE TABLE [Test]
(
    [BookID] [int] NOT NULL,
    [Name] [varchar](512) NOT NULL,

    CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED ([BookID] ASC)
) ON [PRIMARY]

然后当我运行时:

BEGIN TRAN;

INSERT INTO Test (BookID, Name) Values (1,'one');
INSERT INTO Test (BookID, Name) Values (2,'Two');
INSERT INTO Test (BookID, Name) Values (1,'Three');
INSERT INTO Test (BookID, Name) Values (4,'Four');

COMMIT TRAN;

我希望Test 中没有任何内容,因为insert (1, 'Three') 会产生错误

违反主键约束“PK_Test”

但实际上带有BookId = 1, 2, 4 的行在表中。

如果我SET XACT_ABORT ON,那么我会得到预期的行为。

然后换另一段代码的时候报错就好了

由于“ACTIVE_TRANSACTION”,数据库“MyDatabase”的事务日志已满

事务回滚工作

为了确保得到回滚,我应该在 TRY ... COMMIT CATCH ROLLBACK 语句中包含该语句。

但我仍然想知道为什么没有 ROLLBACK 的 BEGIN TRAN 不能一直工作。它真的像我猜的那样取决于错误的类型吗?

【问题讨论】:

  • 当您需要多个语句是原子的时,您应该使用 try/catch 块。这就是他们的目的。

标签: sql-server transactions commit rollback


【解决方案1】:

但我仍然想知道为什么没有 ROLLBACK 的 BEGIN TRAN 不能一直工作。它真的像我猜的那样取决于错误的类型吗?

你是对的,这取决于错误的类型。下面 Erland 的陈述帮助我更多地了解 SQL Server 中错误处理的不同变体。

SQL Server 中的错误处理是一个非常混乱的故事。我问了与您在 1993 年左右在 comp.databases.sybase 中所做的相同的问题。我不记得我得到了什么答案,但我认为它们不是很好。

但事实是这样的:当 SQL Server 中发生错误时,批处理可能会中止并且事务回滚。或者语句可能被终止,事务继续进行。

请不要问这里面的逻辑,因为没有。数据完整性违规通常不会中止批处理。但经常会出现转换错误。

在微软的辩护中,可以说,当产品还是 Sybase 时,许多这些错误的决定都是在加利福尼亚州做出的。另一方面,Microsoft 非常努力地解决这个问题,而不是相反。

查看以下不同场景的截图

此链接包含有关每种行为的出色信息

Error and Transaction Handling in SQL Server

这个错误

由于“ACTIVE_TRANSACTION”,数据库“MyDatabase”的事务日志已满

可能有很多原因。一些包括

  1. 您有一个活动事务正在呈现日志空间重用
  2. 繁重的事务可能需要大量日志空间并且您的磁盘可能已满

其他参考:

https://social.msdn.microsoft.com/Forums/sqlserver/en-US/6ae24a04-0ad3-4aba-b471-2bbbcd8d8626/with-the-transaction-primary-key-violation-error?forum=transactsql

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-16
    • 1970-01-01
    • 2014-09-28
    • 1970-01-01
    • 1970-01-01
    • 2015-06-24
    • 1970-01-01
    • 2016-02-14
    相关资源
    最近更新 更多