先执行select @@sql_mode确认是否由strict_trans_tables等严格模式导致写入失败,再结合报错信息锁定问题;临时用set session sql_mode='no_engine_substitution'验证,永久修改需在[mysqld]段配置sql_mode并重启服务。

确认是不是sql_mode导致写入失败
别急着改配置,先验证问题根源。执行 SELECT @@sql_mode;,重点看输出里有没有 STRICT_TRANS_TABLES、NO_ZERO_DATE、ERROR_FOR_DIVISION_BY_ZERO 这类模式。再结合具体报错——比如 Field 'xxx' doesn't have a default value 或 Incorrect datetime value: '0000-00-00',基本就能锁定是 strict 模式在起作用。
临时绕过:只对当前连接生效
开发或测试环境快速验证时,用 SET SESSION sql_mode = 'NO_ENGINE_SUBSTITUTION'; 即可。注意:SESSION 不影响其他连接,也不需要重启 MySQL;但一旦断连重连就失效。别用 SET SESSION sql_mode = '',空值会触发 MySQL 默认行为(8.0 就是严格模式),反而更糟。
永久生效:配置文件必须写对位置和语法
编辑 /etc/my.cnf 或 /etc/mysql/mysql.conf.d/mysqld.cnf,确保在 [mysqld] 段下写:
sql_mode = "STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,NO_ZERO_IN_DATE"
关键点:
- 必须写在
[mysqld]下,不是[client]或[mysql] - 值要用双引号包裹,且中间不能有空格(MySQL 8.0 对格式敏感)
- 改完必须重启服务:
sudo systemctl restart mysql - 重启后执行
SELECT @@global.sql_mode;确认是否加载成功
ORM 或连接驱动会悄悄覆盖 sql_mode
即使全局配置生效,应用层也可能在建连时重设。比如 Peewee 默认会加 sql_mode='TRADITIONAL';Java 的 JDBC URL 若带 ?sessionVariables=sql_mode=...,也会覆盖配置文件。排查方法:
- 查应用代码里数据库初始化部分,看是否显式传了
sql_mode参数 - 开 MySQL 的 general_log:
SET GLOBAL general_log = 1;,然后复现一次写入,看日志里有没有SET sql_mode = ...这样的语句 - 云数据库(如阿里云 RDS)通常禁止修改全局
sql_mode,只能靠连接串或 init_command 动态设置
真正麻烦的从来不是配置怎么写,而是你改了配置,却不知道哪段代码或哪个中间件正在默默把它再改回去。











