本文提供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
我这个问题归根结底还是自己语句没有写严谨,本地环境不严格,就没排查出来。
所以两种方案,一种是把模式放宽,顺其自然。另一种是保持严格,把语句写严谨。我个选了第二种。