我们有一个流程,需要在 SQL 脚本针对生产数据库运行之前对其进行测试。该方法是在事务中执行脚本,并在最后使用回滚语句,捕获之前/之后的日志来阐明脚本的效果。
select now();
start transaction;
select 'data before any changes', ...;
<insert / update / delete statements>;
select 'data after changes', ...;
rollback;
我们在 MSSQL 上使用这种方法已经很多年了,但是在 mysql 上实现时遇到了麻烦。如果一切都按计划进行,那么一切都很好并且完全按照预期进行。但是,如果我们遇到任何错误(例如:SQL 中的拼写错误或表约束违规),脚本将中止...但会提交错误之前运行的任何内容!!
这如何被认为是一个可以接受的结果?如果错误情况导致提交更改,则会大大降低事务的有效性。我对这种行为感到惊讶——根本无法理解其中的原理。
我一直在寻找解决方案,但基本上空手而归。我见过的选项:
DECLARE ... HANDLER FOR ...;
发生错误时回滚。这看起来很有希望,但似乎只在存储过程(或类似过程)中受支持,因此不适合一次性脚本。我错过了什么?谢谢
终于找到了答案——显然我们的 MySQL 实例(在某处)配置了
autocommit=1
。
现在我们的脚本看起来像:
select now();
set autocommit=0;
start transaction;
select 'data before any changes', ...;
<insert / update / delete statements>;
select 'data after changes', ...;
rollback;
如果脚本遇到错误(无论是语法问题还是更新语句中的关键违规),事务都会回滚!