【问题标题】:Transaction waits for committ and otherwise blocks resources事务等待提交,否则阻塞资源
【发布时间】:2020-06-24 13:41:10
【问题描述】:

我想将一些语句放入事务块中,以便在出现任何错误时脚本回滚。我像这样将事务与TRY 块结合起来(注意INSERT 语句应该通过语法错误):

begin try
    begin tran
    SET ANSI_NULLS ON
    SET QUOTED_IDENTIFIER ON

    CREATE TABLE [MY_DATABASE].[dbo].[MY_TABLE](
        [Id] [nchar](10) NULL,
        [Name] [nchar](10) NULL
    ) ON [PRIMARY]

    insert into [MY_DATABASE].[dbo].[MY_TABLE] (Id,Name) values ('1','Vampire'),  ('2')
    commit tran
end try
begin catch
    rollback tran
end catch

运行此语句后,我注意到我无法在 Management Studio 中获取其他表,并且该操作正在等待我提交。

如何更改我的事务尝试块,以便在出现任何错误时回滚到begin try 语句之前的位置?

【问题讨论】:

  • TRY...CATCH 不会“捕获”语法错误。您需要自己在代码中解决这些问题。
  • @Larnu 你是对的。但你认为它会起作用吗?
  • 如果错误是TRY...CATCH 捕获的,那么是的,那么上面应该可以工作。最简单的判断方法是修复语法错误并进行测试。
  • @Larnu 真的。但是我们怎么知道这个不可预测的错误是TRY 可以CATCH 吗?如果我们解决了语法错误,是否保证 try 块有效?

标签: sql sql-server database transactions


【解决方案1】:

您的脚本提前停止,而不是执行catch 块。令人不满意的答案是,这是TRY/CATCH doesn't handle 的那些事情之一。

SQL Server 启动事务,创建表,然后崩溃

消息 10709,第 16 级,状态 1,第 117 行 表值构造函数中每一行的列数必须相同。

离开打开的事务(这就是您无法在 Mgmt Studio 中获取其他表的原因)。

begin try
    begin tran
    SET ANSI_NULLS ON
    SET QUOTED_IDENTIFIER ON

    CREATE TABLE [dbo].[MY_TABLE](
        [Id] [nchar](10) NULL,
        [Name] [nchar](10) NULL
    ) ON [PRIMARY]

    insert into [dbo].[MY_TABLE] (Id,Name) values ('1','Vampire'),  ('2')
    commit tran
end try
begin catch
    print 'Now inside the "catch" block.  You will not see this message.';
    rollback tran
end catch

go
select * from MY_TABLE;
select @@trancount as TranCount;

rollback tran;

输出如下。注意表的存在和打开的事务:

Msg 10709, Level 16, State 1, Line 117
The number of columns for each row in a table value constructor must be the same.
Id         Name
---------- ----------

(0 rows affected)

  TranCount
-----------
          1

(1 row affected)

【讨论】:

  • 是的。我认为这是导致此锁定的语法错误。所以如果语法正确并且脚本在事务中返回了另一种类型的错误,我的代码会工作吗?
  • 因为这基本上就是我们使用这些交易的原因。如果它运行到一半,然后在运行过程中停止进程,那么拥有它们有什么意义。所以,比如说,我纠正了语法错误,然后我需要知道其余的都可以。
  • 是的,如果语法正确,那么可能出现的任何其他错误确实会按预期被捕获。但是,在您的 catch 块中,请注意 xact_state 并根据该值采取适当的措施。
【解决方案2】:

脚本尚未执行。只有语法错误会导致脚本在执行前抛出错误。什么都没有开始执行。

【讨论】:

  • 那么如果没有执行,为什么还要等待commit呢?
  • 事务是会话的状态。在你的情况下,在显式模式下。它不是“执行”代码。 Begin TRY 不会捕获语法错误。但是状态仍然处于显式事务中,因为在事务状态被引发之后发生语法错误......换句话说,真正执行的序列是 BEGIN TRAN CREATE TABLE 然后语法错误......没有提交,没有回滚
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-31
  • 2011-08-04
  • 2020-11-01
  • 1970-01-01
  • 2022-01-04
  • 1970-01-01
相关资源
最近更新 更多