Liquibase不遵守SQL服务器的RAISERROR。

问题描述 投票:2回答:1

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

RAISERROR @msg, 16, 1

然后SP会返回。SP启动自己的命名事务,他们会回滚提交命名事务,然而,LB并没有检测到提出的错误,它把执行当作成功执行。但如果发生这种情况,我们就不想继续了。

changeSets中的faultOnError被设置为true,但是LB还是会继续执行。即使在DATABASECHANGELOG中,失败的changeSet也被标记为执行成功。

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

我们从事务中去掉了名称,只用BEGIN TRAN,LB的执行就停在了错误的脚本上,但问题是,LB不能提交自己的事务,也不能释放锁,所以仍然是LOCKED。

有沒有辦法告訴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。请注意,我们的脚本不做任何updateinsert,它们只是在一个临时表中提供数据,所以我们的脚本中不做事务处理。在这种情况下,考虑到我们添加了代码,对getMoreResults()进行了调用,异常被正确抛出,但是在LB中,执行者尝试database.rollback(),之后又在StandardLockService中,在释放锁之前,尝试database.rollback(),结果以异常结束,因为我们的SP已经回滚了事务。在LB中的最后一次回滚,导致JDBC引发的错误被吞噬,结果我们不仅看到了引发错误的错误,而且锁仍然没有释放,这是最值得关注的,因为即使我们重新运行脚本并修复它,锁也没有被释放,我们需要手动完成。

也许有人会说我们的事务处理不正确,但我想说的是,如果我们的脚本不正确,释放锁不应该受到影响。LB应该是释放锁,然后抛出异常,或者在脚本changeset没有成功运行时继续。

sql-server liquibase
1个回答
0
投票

如果有人也面临这个问题。在我的案例中,我有一个非常复杂的SQL脚本,只适用于MS SQL Server。这也未能停止执行的LB变化,如果一个错误发生在SQL脚本,无论如何,如果我使用RAISERROR或THROW.的事情,我需要做的,让它工作。

  • 删除(或注释)所有创建结果集的地方(SELECT)。
  • 用 "SET NOCOUNT ON; "来启动SQL脚本,以避免插入或更新的结果(...行受影响)
  • 以 "SET NOCOUNT OFF; "结束SQL脚本,使LB在执行SQL脚本后就能正常工作(设置EXECTYPE)。
© www.soinside.com 2019 - 2024. All rights reserved.