解决:Syntax error or access violation: 1305 SAVEPOINT trans2 does not exist

本文提供MySQL事务报错:PDOException: SQLSTATE[42000]: Syntax error or access violation: 1305 SAVEPOINT trans2 does not exist的一个处理方法。

解决方法

关闭MySQL数据库严格模式,或严谨设置字段默认值。

查看数据库当前模式:SHOW VARIABLES LIKE 'sql_mode'

修改数据库为宽松模式:my.ini,设置为sql_mode=

严谨设置字段默认值:

ALTER TABLE `table_name` ADD `username` VARCHAR NOT NULL DEFAULT ''

处理过程

在写单元测试时遇到这个问题。

本地环境测试一切正常,代码能跑通,无错误。但是拿到CI上去跑,立刻报错,提示Syntax error or access violation: 1305 SAVEPOINT trans2 does not exist

从字面上看,是事务的问题。删除事务,本地能跑通,CI上还是不行。

我将CI上的PHP版本和MYSQL版本调整了一下,和本地统一,还是不行。

查询外国解决方案,貌似Laravel中也遇到不少:https://github.com/laravel/framework/issues/18429

但是百般尝试后,还是没能解决。再仔细一想,可能应该是本地和CI的某些差异。版本号都 统一了,还有什么差异。最多也就是配置上的差异,这时候MYSQL配置成为了主要怀疑对象。

后来删除事在CI跑一下,发现报错是某个字段没有设置默认值。检查了一下,我的字段创建语句确实写的不严谨。

但是本地没有报错?哦,原来是严格模式(Strict Mode)。

CI的MySQL模式:

sql_mode: STRICT_TRANS_TABLES, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER, NO_ENGINE_SUBSTITUTION

而我本地的MySQL模式:

sql_mode: NO_ZERO_IN_DATE, NO_ZERO_DATE, NO_ENGINE_SUBSTITUTION

根源找到了,就是那个STRICT_TRANS_TABLES我这个问题归根结底还是自己语句没有写严谨,本地环境不严格,就没排查出来。

所以两种方案,一种是把模式放宽,顺其自然。另一种是保持严格,把语句写严谨。我个选了第二种。

点赞