唯一能永久关闭mysql 8.0严格模式的方式是修改配置文件并重启服务;登录后执行select @@sql_mode,若含strict_trans_tables或strict_all_tables即已启用,需在[mysqld]段设置不含strict项的sql_mode并重启验证。

怎么确认当前开启了严格模式
登录 MySQL 后执行:SELECT @@sql_mode;,如果返回值里包含 STRICT_TRANS_TABLES 或 STRICT_ALL_TABLES,说明严格模式已启用。注意 ONLY_FULL_GROUP_BY 虽不属于“严格模式”核心项,但常被一并触发报错(比如 GROUP BY 字段不全),实际处理时通常要一并考虑。
为什么不能只用 SET GLOBAL sql_mode = ''
这条命令看似能立刻生效,但有三个硬伤:
- 只影响新建立的连接,已有连接不受影响
- MySQL 重启后自动还原为配置文件定义的值
- 云数据库(如阿里云 RDS、腾讯云 CDB)通常禁用
SET GLOBAL权限,执行会报错Access denied
所以 Docker 容器、K8s 环境或托管服务中,跳过配置文件修改这步,基本等于没关。
如何永久关闭:改 my.cnf 并重启
找到 MySQL 配置文件(Linux 常见路径:/etc/my.cnf 或 /etc/mysql/my.cnf;Windows 是 my.ini),在 [mysqld] 段下添加或修改 sql_mode 行:
sql_mode = "NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
关键点:
- 必须删掉
STRICT_TRANS_TABLES和STRICT_ALL_TABLES—— 这两个才是触发 INSERT 报错Field 'xxx' doesn't have a default value的元凶 - 不要写成
sql_mode = "",MySQL 8.0 会拒绝启动,报错Invalid sql_mode - 别写在
[client]或[mysql]段下,那部分对服务端无效 - 改完必须重启服务:
sudo systemctl restart mysql(或mysqld,依你的服务名而定)
验证是否真正生效
重启后再次执行:SELECT @@GLOBAL.sql_mode;(注意是 @@GLOBAL,不是 @@SESSION)。确认输出中既没有 STRICT_*,也没有 ONLY_FULL_GROUP_BY(除非你明确想保留)。再试一条曾报错的语句,例如向 NOT NULL 字段插 NULL,或省略 GROUP BY 中的非聚合字段 —— 如果不再报错,说明已生效。
最容易被忽略的是:Docker 启动时挂载的配置文件路径是否正确、容器内是否读到了你改的那一份;本地测试没问题,上生产却回退,八成是配置没进对容器,或者用了 docker run --rm 之类丢掉持久化配置的启动方式。











