mysql如何设置SQL模式_mysql sql_mode严格模式调整

3次阅读

mysql如何设置SQL模式_mysql sql_mode严格模式调整

怎么查当前 sql 模式?别猜,直接看

你改没改成功、程序连的是哪个模式,全靠 select @@sql_modeSELECT @@global.sql_mode 说话。前者查当前连接(会话级),后者查全局默认值——但注意:@@global.sql_mode 只影响新建立的连接,已存在的连接不会变。

  • SELECT @@session.sql_modeSELECT @@sql_mode 效果一样,推荐用后者,更简洁
  • 返回结果是一长串逗号分隔的模式名,比如 ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_DATE,顺序无关,mysql 自己解析
  • 如果返回空字符串,说明当前是“宽松模式”,很多非法插入只会警告不报错,容易埋坑

临时改模式:会话级 vs 全局级,别混用

临时改就是不写配置文件、不重启 MySQL 的快速调试方式,但得清楚作用域——不然你会纳闷“我明明 SET 了,为什么 Java 程序还是报错?”

  • 会话级:SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE',只对当前这个命令行 / 连接生效,关掉终端就失效
  • 全局级:SET GLOBAL sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE',新连上来的客户端(比如 spring Boot 重启后的新连接)才会用这个模式;已有连接完全不受影响
  • 常见误操作:在 MySQL 客户端里 SET GLOBAL,然后立刻执行 INSERT 测试——结果还是老模式,因为你的当前会话没刷新,得 EXIT 再重连才生效

永久生效:改配置文件必须重启,且路径和语法有坑

生产环境要稳定,必须走配置文件。但 MySQL 8.0+ 和旧版本写法不同,linuxwindows 路径也不同,配错会导致 MySQL 启动失败。

  • 配置项名是 sql_mode(不是 sql-mode,后者在 MySQL 8.0+ 已废弃,用了会启动失败)
  • Linux 常见路径:/etc/my.cnf/etc/mysql/my.cnf;Windows 是 C:ProgramDataMySQLMySQL Server x.xmy.ini
  • 必须加在 [mysqld] 段落里,例如:
    [mysqld]<br>sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
  • 双引号可选,但建议加上,避免空格或特殊字符引发解析问题;值里不能有多余换行或注释
  • 改完必须 sudo systemctl restart mysql(Linux)或服务管理器重启,光 reload 不行

Strict 模式组合怎么选?别无脑抄 TRADITIONAL

TRADITIONAL 看起来省事,但它等价于 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,其中 NO_AUTO_CREATE_USER 在 MySQL 8.0+ 已彻底移除——你配了它,MySQL 就起不来。

  • 推荐最小可用严格组合:STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
  • ONLY_FULL_GROUP_BY 很有用,但会卡住某些旧业务的 GROUP BY 写法(比如 SELECT a, MAX(b) FROM t GROUP BY a 却选了 c 字段),上线前务必全量回归测试
  • 开发环境可先开 STRICT_TRANS_TABLES 单独试水,它只对事务表严格,风险可控;线上再逐步加其他项

最常被忽略的一点:ORM 框架(比如 mybatishibernate)可能在连接 URL 里硬编码了 sessionVariables=sql_mode=xxx,这时候配置文件和 SET GLOBAL 都会被覆盖——得去检查连接串和初始化 SQL。

text=ZqhQzanResources