什么类型的错误导致 MS SQL Server 中的 XACT_STATE 为 1?

Posted

技术标签:

【中文标题】什么类型的错误导致 MS SQL Server 中的 XACT_STATE 为 1?【英文标题】:What does type of error cause XACT_STATE be 1 in the MS SQL Server? 【发布时间】:2018-05-29 01:06:18 【问题描述】:

基于 Microsoft 文档关于 TRY...CATCH 当 XACT_STATE 为 -1 时,Transactions are Uncommittable (TRY...CATCH (Transact-SQL)):

不可提交的交易和 XACT_STATE

如果在 TRY 块中生成的错误导致当前的状态 交易无效,该交易被归类为 不可提交的交易。 通常会结束交易的错误 在 TRY 块之外导致事务进入不可提交 错误发生在 TRY 块内时的状态。 不可提交 事务只能执行读取操作或 ROLLBACK 交易。事务无法执行任何 Transact-SQL 将生成写操作或 COMMIT 的语句 交易。 XACT_STATE 函数返回值 -1,如果 交易被归类为不可提交交易。什么时候 批处理完成后,数据库引擎回滚任何活动的 不可提交的交易。如果在发送时没有发送错误消息 事务进入不可提交状态,当批处理完成时, 将向客户端应用程序发送一条错误消息。这 表示检测到并滚动了一个不可提交的事务 返回。

如果我理解正确,每个停止 TRY 块连续性并进入 CATCH 块的错误都会导致 XACT_STATE 为 -1(当 XACT_ABORT 为 ON 时),但在上述文档的示例 C 中检查它是否为 1 :

。 . .结束尝试开始捕捉 -- 执行错误检索例程。 执行 usp_GetErrorInfo;

-- Test XACT_STATE:  
    -- If 1, the transaction is committable.  
    -- If -1, the transaction is uncommittable and should   
    --     be rolled back.  
    -- XACT_STATE = 0 means that there is no transaction and  
    --     a commit or rollback operation would generate an error.  

-- Test whether the transaction is uncommittable.  
IF (XACT_STATE()) = -1  
BEGIN  
    PRINT  
        N'The transaction is in an uncommittable state.' +  
        'Rolling back transaction.'  
    ROLLBACK TRANSACTION;  
END;  

-- Test whether the transaction is committable.  
IF (XACT_STATE()) = 1  
BEGIN  
    PRINT  
        N'The transaction is committable.' +  
        'Committing transaction.'  
    COMMIT TRANSACTION;     

END; END CATCH; GO

我的问题在这里:

这是错误的例子吗?如果不是,什么样的错误会导致 CATCH 块中的 XACT_STATE 为 1(可提交)?

【问题讨论】:

【参考方案1】:

SQL Server 可以容忍事务中的一些错误,而不必将其标记为不可提交。例如 SELECT 1/0 会导致错误,但不会强制事务进入不可提交状态。 (引自https://docs.microsoft.com/en-us/azure/sql-data-warehouse/sql-data-warehouse-develop-transactions。)

事实上,除非 XACT_ABORT 开启,几乎任何非致命错误都会产生 1 的 XACT_STATE(pk 违规、数据类型转换、约束违规等)。 (取自https://www.sqlservercentral.com/Forums/Topic1109613-1550-1.aspx)。

【讨论】:

我认为您提到的 MS 文档是错误的。因为我在事务中使用“select 1/0”通过“select XACT_STATE()”命令检查 CATCH 块中的 XACT_STATE 值,所以它返回 -1! 你有 XactAbort 吗?这可能解释了差异。我刚刚编辑了我的答案以包含这些信息。 是的,它已开启。如果我不启用它,XACT_STATE 将为 1(表示可提交)但 PK Violation 等实际上是不可提交的! 我没有说关闭它是正确的。我是说,现在你知道什么样的错误会导致 XACT_STATE 为 1。这是你的问题。 谢谢。我得到了它。当 XACT_ABORT 为 ON 时,所有错误都会导致 XACT_STATE 为 -1,甚至是“SELECT 1/0”,这意味着所有可以在错误源之前提交的 T-SQL 命令都不允许提交,但如果它为 OFF,则错误源如“SELECT 1/0" 允许提交之前的所有命令。因此,我认为当 XACT_ABORT 为 ON 时,在 CATCH 块中检查 XACT_STATE 是否为 1 是徒劳的。

以上是关于什么类型的错误导致 MS SQL Server 中的 XACT_STATE 为 1?的主要内容,如果未能解决你的问题,请参考以下文章

MS SQL Server 中 JSON 函数路径中的重音字符导致错误

比较c#中sql server和ms访问的数据类型

PCB MS SQL SERVER 字段含小写字母更新为大写字母

MS Access 直通选择查询导致 SQL Server 中的页面锁定

Sqoop Hive 字符串数据类型转 MS SQL Server 类型

sql server 中union的用法