Liquibase并不尊重SQL服务器的RAISERROR

时间:2016-09-30 08:47:42

标签: sql-server liquibase

我们有许多配置脚本有点复杂。这些脚本在我们的数据库中使用了许多可用的存储过程来插入配置数据。如果任何脚本试图插入无效数据,存储过程将调用

TakesScreenshot

然后SP将返回。 SP启动它们自己的命名事务,它们将回滚/提交命名事务,但是,LB没有检测到引发的错误,它将执行作为成功执行。但如果发生这种情况,我们不想继续。

changeSets中的

failOnError设置为true,但LB仍然继续。即使在DATABASECHANGELOG中,变更集失败也标记为执行,就好像它是成功的一样。

我们还尝试删除嵌套事务(命名事务),没有运气。

我们从事务中删除了名称并且只使用了BEGIN TRAN,LB执行在不正确的脚本处停止但问题是,LB无法提交自己的事务并且无法释放锁定以使其保持锁定状态。

有没有告诉LB发生错误并让它停止?

  

我们正在使用Liquibase 3.5.0。和Microsoft SQL Server

===编辑

所以在调试Liquibase之后,我们发现了两件事:

  1. 当连接到MS SQL Server时,如果发生RAISERROR并且脚本中也有结果集,除非我们调用statement.getMoreResults(),否则它不会抛出异常。 Sybase也是如此(我们也使用Sybase对其进行了测试)。所以我们认为可能在LB中,在执行语句之后我们需要调用getMoreResults()直到它抛出异常或者返回false,这意味着没有发生错误。

  2. 脚本调用存储过程。存储过程有“BEGIN TRAN'最后它是COMMIT或ROLLBACK。如果发生回滚,它也会执行RAISERROR。请注意,我们的脚本不进行任何更新/插入,它们只提供临时表中的数据,因此我们不会在脚本中进行事务处理。在这种情况下,考虑我们添加代码来调用getMoreResults(),异常正确抛出然后在LB中,执行程序尝试使用database.rollback()然后再次在StandardLockService中,在释放锁之前,它会尝试到database.rollback()以异常结束,因为我们的SP已经回滚了事务。 LB中的最后一次回滚导致JDBC引发的错误被吞下,结果我们不仅看到导致它的错误,而且锁定仍然未发布,这是最关心的,因为即使我们重新运行脚本并修复它,锁没有被释放,我们需要手动完成。

  3. 有人可能会说我们的事务处理不正确,但我想说的是,如果我们的脚本不正确,释放锁定不应该影响。如果脚本/变更集未成功运行,LB应该释放锁并抛出异常或继续。

2 个答案:

答案 0 :(得分:0)

如果有人也面临这个问题:就我而言,我只有MS SQL Server有一个非常复杂的SQL脚本。如果在SQL脚本中发生错误,无论如何,如果我使用RAISERROR或THROW,这也都无法停止LB更改的执行。 我需要做的事情才能使其正常工作:

  • 删除(或注释)所有创建结果集的地方(选择)
  • 使用“ SET NOCOUNT ON;”启动SQL脚本。避免来自 插入或更新(...受影响的行)
  • 以“ SET NOCOUNT OFF;”结束SQL脚本。使LB在执行SQL脚本(设置EXECTYPE)之后能够正常工作

答案 1 :(得分:0)

使用前提条件https://docs.liquibase.com/concepts/advanced/preconditions.html

创建另一个变更集,并在执行下一步之前检查执行结果。