前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >MySQL的sql_mode详解:从优雅草分发平台故障谈数据库模式配置-优雅草卓伊凡

MySQL的sql_mode详解:从优雅草分发平台故障谈数据库模式配置-优雅草卓伊凡

原创
作者头像
卓伊凡
发布于 2025-05-12 13:18:03
发布于 2025-05-12 13:18:03
15700
代码可运行
举报
文章被收录于专栏:其他相关技术其他相关技术
运行总次数:0
代码可运行

MySQL的sql_mode详解:从优雅草分发平台故障谈数据库模式配置-优雅草卓伊凡

引言:优雅草分发平台的故障与解决

近日,优雅草分发平台(youyacaocn)在运行过程中遭遇了一次数据库访问故障。在排查过程中,技术人员发现问题的根源在于MySQLsql_mode设置过于严格,导致部分SQL语句执行失败。通过将sql_mode调整为宽松模式(NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION)并重启MySQL服务,问题得以解决。

这一案例引发了我们对MySQL sql_mode的深入思考:

  • sql_mode到底是什么?
  • 它有哪些模式?各自的作用是什么?
  • 不同模式的应用场景如何选择?
  • 如何正确配置以避免类似问题?

本文将从基础概念入手,详细解析MySQL的sql_mode,并结合实际案例探讨其优化策略。


一、MySQL的sql_mode是什么?

1.1 定义

sql_mode是MySQL的一个系统变量,用于控制SQL语句的解析和执行方式。它决定了MySQL如何处理数据校验、语法兼容性、存储引擎行为等。

1.2 作用

  • 数据校验:控制是否允许插入无效数据(如空值、超出范围的值)。
  • SQL语法兼容性:调整MySQL的SQL解析行为,使其更符合ANSI SQL标准或其他数据库(如Oracle、PostgreSQL)的行为。
  • 存储引擎行为:影响存储引擎的默认行为,如自动替换不可用的引擎。

1.3 为什么需要调整sql_mode?

  • 严格模式(Strict Mode):适用于新项目,确保数据完整性,但可能导致旧系统SQL报错。
  • 宽松模式(Loose Mode):适用于兼容旧系统,允许某些非标准SQL执行,但可能牺牲数据安全性。

在优雅草平台的案例中,由于某些SQL语句不符合严格模式的要求,导致查询失败,调整sql_mode后恢复正常。


二、MySQL的sql_mode有哪些模式?

MySQL的sql_mode支持多种模式,可以单独或组合使用。以下是常见的模式及其用途:

2.1 严格模式(Strict Mode)

模式

作用

STRICT_TRANS_TABLES

对事务型存储引擎(如InnoDB)启用严格模式,拒绝非法数据(如超出范围的值)。

STRICT_ALL_TABLES

对所有存储引擎启用严格模式,非法数据会报错而非警告。

影响

  • 插入NULL到非空列会报错,而不是自动填充默认值。
  • 插入超出范围的值(如999999TINYINT字段)会报错,而不是截断。

适用场景

  • 新项目,需要严格数据校验。
  • 金融、医疗等对数据准确性要求高的系统。

2.2 日期处理模式

模式

作用

NO_ZERO_DATE

禁止0000-00-00作为有效日期。

NO_ZERO_IN_DATE

禁止2020-00-01或2020-01-00这样的非法日期。

ALLOW_INVALID_DATES

允许部分无效日期(如2020-02-30),仅校验月份范围。

影响

  • 在严格模式下,0000-00-00会被拒绝,而宽松模式下可能允许。

适用场景

  • 需要兼容旧系统时,可能需要关闭NO_ZERO_DATE
  • 新系统建议启用,避免非法日期数据。

2.3 分组查询模式

模式

作用

ONLY_FULL_GROUP_BY

要求GROUP BY必须包含所有非聚合列,避免歧义查询。

示例

代码语言:javascript
代码运行次数:0
运行
复制
-- 如果启用ONLY_FULL_GROUP_BY,以下查询会报错:
SELECT user_id, username, COUNT(*) FROM users GROUP BY user_id;
-- 必须改为:
SELECT user_id, username, COUNT(*) FROM users GROUP BY user_id, username;

适用场景

  • 数据分析系统,确保GROUP BY查询结果准确。
  • 旧系统可能需要关闭此模式以兼容原有SQL。

2.4 存储引擎模式

模式

作用

NO_ENGINE_SUBSTITUTION

如果指定存储引擎不可用(如ENGINE=MyISAM但未安装),报错而非自动替换为默认引擎。

影响

  • 启用时,建表语句必须使用可用的引擎,否则报错。
  • 关闭时,MySQL会自动替换为默认引擎(如InnoDB)。

适用场景

  • 需要确保存储引擎一致性时启用(如强制使用InnoDB)。
  • 旧系统可能需要关闭以兼容MyISAM表。

2.5 用户管理模式

模式

作用

NO_AUTO_CREATE_USER

禁止GRANT语句自动创建用户(MySQL 8.0已默认移除此模式)。

影响

  • 启用时,GRANT语句必须搭配CREATE USER使用。
  • 关闭时,GRANT会自动创建不存在的用户。

适用场景

  • 需要更严格的用户权限管理时启用。
  • 旧系统可能需要关闭以兼容自动创建用户的SQL。

2.6 其他常见模式

模式

作用

ANSI

使MySQL更符合ANSI SQL标准(如`

`作为字符串连接符)。

TRADITIONAL

组合模式,包含严格校验、禁止零日期等,接近传统SQL行为。

PIPES_AS_CONCAT

将`

`视为字符串连接符(默认是OR逻辑运算符)。


三、如何选择合适的sql_mode?

3.1 推荐组合

场景

推荐模式

新项目(严格模式)

STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,ONLY_FULL_GROUP_BY

旧系统兼容模式

NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION(如优雅草平台所用)

ANSI标准兼容

ANSI(包含PIPES_AS_CONCAT,ANSI_QUOTES等)

3.2 查询当前sql_mode

代码语言:javascript
代码运行次数:0
运行
复制
SHOW VARIABLES LIKE 'sql_mode';
--SELECT @@GLOBAL.sql_mode, @@SESSION.sql_mode;

3.3 修改sql_mode

临时修改(当前会话)
代码语言:javascript
代码运行次数:0
运行
复制
SET SESSION sql_mode = 'NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
永久修改(配置文件)

my.cnfLinux)或my.ini(Windows)中添加:

代码语言:javascript
代码运行次数:0
运行
复制
[mysqld]
sql_mode = NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

然后重启MySQL:

代码语言:javascript
代码运行次数:0
运行
复制
systemctl restart mysql

四、总结与最佳实践

4.1 优雅草平台故障回顾

  • 问题sql_mode设置过严,导致SQL执行失败。
  • 解决方案:调整为NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,重启MySQL后恢复。

4.2 最佳实践

  1. 新项目:启用严格模式(STRICT_TRANS_TABLES),确保数据完整性。
  2. 旧系统迁移:先使用宽松模式,逐步调整SQL适配严格模式。
  3. 存储引擎管理:启用NO_ENGINE_SUBSTITUTION,避免引擎自动替换。
  4. 日期处理:启用NO_ZERO_DATE,避免非法日期数据。

4.3 思考

MySQL的sql_mode是一个强大的工具,合理配置可以避免许多潜在问题。通过这次优雅草平台的故障修复,我们更深刻地认识到:数据库的灵活性需要与数据安全性平衡,选择合适的sql_mode数据库优化的重要一环。


希望这篇文章能帮助大家深入理解MySQL的sql_mode,并在实际项目中合理应用! 🚀

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
MySQL的sql_mode模式说明及设置
sql_mode是个很容易被忽视的变量,默认值是空值,在这种设置下是可以允许一些非法操作的,比如允许一些非法数据的插入。在生产环境必须将这个值设置为严格模式,所以开发、测试环境的数据库也必须要设置,这样在开发测试阶段就可以发现问题。
星哥玩云
2022/08/18
2.1K0
MySQL 报错:5.7版本sql_mode=only_full_group_by问题
MySQL 5.7.9版本sql_mode=only_full_group_by问题 用到GROUP BY 语句查询时com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column ‘col_user_6.a.START_TIME’ which is not functional
学到老
2018/03/19
1.4K0
MySQL案例:sql_mode详解
相信看过上一篇文章《MySQL案例:一个数据丢失惨》的童鞋,都应该意识到,sql_mode是一个非常关键的配置,接下来就带来该配置项的详细解析。
brightdeng@DBA
2020/12/12
1.9K0
MySQL案例:sql_mode详解
MySQL sql_mode
sql_mode是个很容易被忽视的变量,默认值是空值,在这种设置下是可以允许一些非法操作的,比如允许一些非法数据的插入。在生产环境必须将这个值设置为严格模式。所以开发、测试环境的数据库也必须要设置,这样在开发测试阶段就可以发现问题。
用户10325771
2023/03/01
6650
MySQL5.7 中使用 group by 报错 this is incompatible with sql_mode=only_full_group_by
这个错误发生在mysql 5.7 版本及以上版本,5.7版本默认的sql_mode配置中包含 ONLY_FULL_GROUP_BY,这个配置严格执行了”SQL92标准”
很酷的站长
2023/01/02
2.5K1
MySQL5.7 中使用 group by 报错 this is incompatible with sql_mode=only_full_group_by
【数据库】MySql的sql_mode模式说明
mysql5.7+的版本中,sql_mode为严格模式。比如必须给字段默认值,更新数据的长度必须符合限制等。
参谋带个长
2023/04/28
1.8K0
sql_mode兼容性,MySQL 8.0 升级踩过的坑
MySQL 8.0从GA到现在已经过去4年了,被各大互联网公司广泛使用,稳定性得到了充分的验证。最近,我们也在将存量的旧版本数据库升级到8.0。虽然前期做了很多的检查和验证,不过升级过程中终究免不了踩一些坑。
吹水老王
2022/05/17
6.5K0
sql_mode兼容性,MySQL 8.0 升级踩过的坑
MySQL的sql_mode设置导致报错1292
字面意思很明显,是数据格式的问题,默认情况下MySQL都设置了严厉模式,不同于Oracle默认的相对宽松的模式,8.0版本的这些严厉模式包括建表时不允许没有主键,插入日期型数据不能为0或其他非法格式等等,这些模式的设置会导致在数据迁移、兼容性测试时报错,要么修改应用限制以适配数据库,要么修改数据库配置以适配已有的应用。
雪人
2022/10/13
9270
MySQL sql_mode的坑及严格模式详解
mysql可以为不同的客户端设置不同的sql_mode,并且每个应用能够设置他自己的会话级别的sql_mode。sql_mode会影响sql语法以及mysql显示数据的正确性。
Petrochor
2022/06/07
2.9K0
SQL_MODE之ONLY_FULL_GROUP_BY
这个是由于MySQL在5.7版本中添加了一个sql_mode: ONLY_FULL_GROUP_BY,当配置了此sql_mode后,select语句中要查询的字段必须严格是group by语句中的字段或者是聚合函数。
俗可耐
2018/09/13
2K0
mysql sql-mode 解析和设置
sql_mode:简而言之就是:它定义了你MySQL应该支持的sql语法,对数据的校验等等
yaphetsfang
2020/07/30
1.7K0
【MySQL】MySQL配置中sql_mode的作用
不知道你有没有踫到过这种问题,在 MySQL8 默认的情况下,我们之前习惯的为 DateTime 类型指定的 0000-00-00 这种格式是无法插入或者修改数据的。其实这种情况就是 MySQL 模式设置的问题,也就是我们今天要讲的 sql_mode 这个参数属性的作用。
硬核项目经理
2024/03/26
2770
【MySQL】MySQL配置中sql_mode的作用
sql_mode之only_full_group_by
今天上班的时候,业务方问了我这样一个问题:能不能把线上的sql_mode值改为和测试环境一致?因为我们在测试环境上写的sql在线上可能会出错,原因是线上的环境设置了sql_mode=only_full_group_by。
AsiaYe
2019/11/06
3.8K0
MySQL系列之SQL_MODE学习笔记
SQL_MODE:MySQL特有的一个属性,用途很广,可以通过设置属性来实现某些功能支持
SmileNicky
2022/05/07
7500
MySQL系列之SQL_MODE学习笔记
mysql 5.7 sql_mode设置问题
在mysql较低版本中,对SQL语句并没有严格的限制检查,在5.7及以上版本开启严格模式,在插入数据的时候,如果字段没有设置默认值,则会报类似于这样的错误:“Field ‘title’ doesn’t have a default value”。
参谋带个长
2022/04/28
1.4K0
[905]MySQL的sql_mode解析与设置和MySQLdb._exceptions.OperationalError: (1055, “Expression
重启mysql:/etc/init.d/mysql restart 登录mysql:mysql -u root -p mysql ->select @@sql_mode; 验证sql_mode的值是否改变。
周小董
2020/10/29
1.2K0
使用MySQL这么久,你了解sql_mode吗?
前面一篇文章《案例| +1s导致的故障》介绍了因为开发同学对datetime值+1s的操作导致的问题。我们在复盘的时候讨论设置sql_mode为严格模式可行性。于是有了此文。
用户1278550
2020/09/01
5.8K0
使用MySQL这么久,你了解sql_mode吗?
MySQL中的sql_mode参数
对于group by聚合操作,如果在select中的列,没有在group by中出现,那么将认为这个sql是不合法的,因为列不在group by从句中。这里我们通过一个例子来看:
AsiaYe
2019/11/06
1.6K0
mysql的sql_mode模式
在oracle或sqlserver中,如果某个表的字段设置成not null,insert或update时不给这个字段赋值,比如下面这样: 表t_test(id,name)中id,name都不允许为空, insert into t_test(name) values('xxx') 必然报错,这是天经地义的事情,但是在mysql中这是有可能成功,具体取决于sql_mode的设置 大概上讲,sql_mode可以分为二大类: 一类是所谓的宽松无敌模式(my.ini中sql_mode设置为空或仅NO_ENGINE_
菩提树下的杨过
2018/01/18
1.2K0
MySQL中的SQL Mode及其作用
与其它数据库不同,MySQL可以运行在不同的SQL Mode下。SQL Mode定义MySQL应该支持什么样的SQL语法,以及它应该执行什么样的数据验证检查。
数据和云
2021/07/30
1.9K0
相关推荐
MySQL的sql_mode模式说明及设置
更多 >
目录
  • MySQL的sql_mode详解:从优雅草分发平台故障谈数据库模式配置-优雅草卓伊凡
    • 引言:优雅草分发平台的故障与解决
    • 一、MySQL的sql_mode是什么?
      • 1.1 定义
      • 1.2 作用
      • 1.3 为什么需要调整sql_mode?
    • 二、MySQL的sql_mode有哪些模式?
      • 2.1 严格模式(Strict Mode)
      • 2.2 日期处理模式
      • 2.3 分组查询模式
      • 2.4 存储引擎模式
      • 2.5 用户管理模式
      • 2.6 其他常见模式
    • 三、如何选择合适的sql_mode?
      • 3.1 推荐组合
      • 3.2 查询当前sql_mode
      • 3.3 修改sql_mode
    • 四、总结与最佳实践
      • 4.1 优雅草平台故障回顾
      • 4.2 最佳实践
      • 4.3 思考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验