【问题标题】:Why is the SQL transaction not being rolled back?为什么 SQL 事务没有被回滚?
【发布时间】:2012-03-06 14:47:20
【问题描述】:

这是删除了不必要部分的脚本

USE databaseName

BEGIN TRY 
    DECLARE @count INT 
    DECLARE @ErrorMsg VARCHAR(MAX) 

    SET @count=(SELECT COUNT(*) 
                FROM   xxxtable 
                WHERE  xxxcolumn = 'xxx') 

    IF( @count = 0 ) --This means that the script has not been run yet      
      BEGIN 
          BEGIN TRANSACTION 

          --do work in here 
          COMMIT TRANSACTION 
      END 
    ELSE 
      BEGIN 
          SELECT 'This script has already been run before. Cannot run it again.' 
      END 
END TRY 

BEGIN CATCH 
    IF( Xact_state() <> 0 ) 
      BEGIN 
          ROLLBACK TRAN 

          PRINT( 'ROLLED BACK TRANSACTION' ) 

          SELECT Error_number()  AS error_number, 
                 Error_line()    AS error_line, 
                 Error_message() AS error_message 
      END 
END CATCH 

脚本失败时,进入catch块,打印ROLLED BACK TRANSACTION,同时显示select语句结果(错误信息等)。

但是当我签入数据库时​​,直到故障点的数据才被提交。我在这里做错了什么?

更新:回滚数据后,可用的最新身份值发生变化。 (假设可用的最高标识是 10,如果我插入并回滚,可用的最高标识是 11 而不再是 10)。所以回滚是不会将数据库返回到事务之前的状态。这就是造成问题的原因。

【问题讨论】:

  • 是否有可能在剥离的代码中隐藏了提交?您是否尝试过监视语句的执行以查看何时发生提交,分别对数据库进行了更改?
  • 在条带代码中没有提交。如上面的脚本所示,最后只有一个提交:(
  • 脚本失败时您收到什么错误消息?
  • 您可能已经删除了有助于我们找到问题的部分。如果您使用 if exists 语句进行插入并且 if exists 不正确,则它可能会跳过该步骤而不是例如失败。或者,如果您使用动态 SQL,则问题可能出在于此。没有看到实际代码,很难知道发生了什么
  • 数据库存储SSN等敏感数据,发布实际代码可能危及数据库安全:(.

标签: sql-server-2008 transactions


【解决方案1】:

根据您的 更新 re: IDENTITY 值,这是预期行为。回滚不会重置 IDENTITY 值,因此会在您的 ID 值中产生间隙。

大概这就是您说“提交故障点之前的数据”时的意思 - 不是您在事务中更新/插入的所有数据在假设回滚。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-18
    • 2018-11-08
    • 1970-01-01
    • 1970-01-01
    • 2020-04-28
    • 1970-01-01
    • 2020-05-01
    相关资源
    最近更新 更多