我们有一些配置脚本,这些脚本有点复杂。这些脚本使用数据库中一些可用的存储过程来插入配置数据。如果任何脚本试图插入无效的数据,存储过程会调用
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之后,我们发现了两件事。
当连接到MS SQL Server时,如果发生了RAISERROR,并且脚本中也有结果集,它不会抛出异常,除非我们调用statement.getMoreResults()。同样的事情也发生在Sybase上(我们也用Sybase测试过)。所以我们想,也许在LB中,在执行完语句后,我们需要调用getMoreResults(),直到它抛出异常或返回false,即没有发生错误。
一个脚本对一个存储过程进行调用。这个存储过程,有'BEGIN TRAN',最后要么COMMIT要么ROLLBACK。如果发生回滚,它也会做RAISERROR。请注意,我们的脚本不做任何updateinsert,它们只是在一个临时表中提供数据,所以我们的脚本中不做事务处理。在这种情况下,考虑到我们添加了代码,对getMoreResults()进行了调用,异常被正确抛出,但是在LB中,执行者尝试database.rollback(),之后又在StandardLockService中,在释放锁之前,尝试database.rollback(),结果以异常结束,因为我们的SP已经回滚了事务。在LB中的最后一次回滚,导致JDBC引发的错误被吞噬,结果我们不仅看到了引发错误的错误,而且锁仍然没有释放,这是最值得关注的,因为即使我们重新运行脚本并修复它,锁也没有被释放,我们需要手动完成。
也许有人会说我们的事务处理不正确,但我想说的是,如果我们的脚本不正确,释放锁不应该受到影响。LB应该是释放锁,然后抛出异常,或者在脚本changeset没有成功运行时继续。
如果有人也面临这个问题。在我的案例中,我有一个非常复杂的SQL脚本,只适用于MS SQL Server。这也未能停止执行的LB变化,如果一个错误发生在SQL脚本,无论如何,如果我使用RAISERROR或THROW.的事情,我需要做的,让它工作。