在 Linux 下的 MySQL(包括 8.0 版本)中,/etc/mysql/my.cnf 文件里的这两行代码:

  1. !includedir /etc/mysql/conf.d/
  2. !includedir /etc/mysql/mysql.conf.d/

是 MySQL 配置文件的包含指令(Include Directive)。下面为你详细解释它的含义和作用:

1. 核心含义:!includedir 是什么?

!includedir 是 MySQL 读取配置文件时的一个特殊指令,意思是:

“在读取当前配置文件(my.cnf)的过程中,顺带去读取指定目录下所有以 .cnf 为后缀的配置文件,并将它们的内容合并到当前配置中。”

也就是说,MySQL 启动时会按以下顺序“拼接”配置:

  1. 先读取 /etc/mysql/my.cnf 本身的内容。
  2. 遇到 !includedir /etc/mysql/conf.d/ 时,按字母顺序读取该目录下所有 .cnf 文件。
  3. 遇到 !includedir /etc/mysql/mysql.conf.d/ 时,同样按字母顺序读取该目录下所有 .cnf 文件。

2. 为什么要这样设计?(模块化配置)

这种设计主要是为了配置管理的模块化和安全性:

  • 解耦与清晰:不用把所有配置都堆在一个 my.cnf 文件里,不同的功能(如主服务、客户端、自定义调优)可以分开放在不同的文件里。
  • 避免升级冲突:通过包管理器(如 apt 或 yum)升级 MySQL 时,主配置文件 my.cnf 可能会被更新覆盖。如果你把自定义配置放在子目录(如 conf.d)里,升级就不会影响你的配置。
  • 方便软件包管理:不同的 MySQL 相关软件包(如 mysql-server, mysql-client)可以只往这些目录里丢自己的配置文件,互不干扰。

3. 这两个目录通常有什么区别?

在 Debian/Ubuntu 等 Linux 发行版中,这两个目录的分工通常是:

  • /etc/mysql/conf.d/:
    • 通常用于存放用户自定义的通用配置,或者一些可选的插件配置。
    • 你可以自己在这里新建一个 .cnf 文件来覆盖默认设置(比如调大连接数)。
  • /etc/mysql/mysql.conf.d/:
    • 通常用于存放 MySQL 服务器核心运行参数(最重要的 [mysqld] 段落)。
    • 比如 Ubuntu 上安装 MySQL 后,主要的服务器配置(数据目录 datadir、端口、socket、日志路径等)通常位于该目录下的 mysqld.cnf 文件中。

4. 配置的优先级与覆盖规则

  • 后加载的覆盖先加载的:如果多个配置文件里设置了同一个参数(例如都设置了 max_connections),那么字母排序靠后的文件,或者后一个 !includedir 目录中的配置会生效。
  • 目录内的读取顺序:同一个目录下,MySQL 会按照文件名的字母顺序依次读取。例如 00-default.cnf 会先于 zz-custom.cnf 被读取,因此 zz-custom.cnf 里的配置可以覆盖前者。

5. 使用注意事项

  1. 只认 .cnf 后缀:目录下如果不是以 .cnf 结尾的文件(比如备份文件 mysqld.cnf.bak),MySQL 会直接忽略。
  2. 修改后需重启/重载:修改了这些目录下的任何配置文件后,需要执行 systemctl restart mysql(或 mysqld)才能使配置生效。
  3. 语法正确:确保你新建的 .cnf 文件格式正确(如包含 [mysqld] 等段名),否则可能导致 MySQL 启动失败。

在 Linux 的 MySQL 8.0 中,配置 sql_mode 推荐修改以下两个位置之一(效果相同,取决于你的管理习惯):

1. 推荐方案:修改主服务配置文件

直接编辑 MySQL 服务端的主配置文件:

  1. sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf

在文件末尾(或找到 [mysqld] 区块)添加如下内容:

  1. [mysqld]
  2. sql_mode=STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION

说明:/etc/mysql/mysql.conf.d/mysqld.cnf 是 Ubuntu/Debian 系发行版中 MySQL 服务器核心参数的默认存放位置,优先级较高。


2. 自定义方案:在 conf.d 目录下新建文件(防升级覆盖)

如果你希望配置与系统默认文件完全解耦(升级 MySQL 时不会被覆盖),可以在 /etc/mysql/conf.d/ 目录下新建一个自定义的 .cnf 文件:

  1. sudo vim /etc/mysql/conf.d/sql-mode.cnf

写入以下内容(必须包含 [mysqld] 段名):

  1. [mysqld]
  2. sql_mode=STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION

文件名随意,但必须以 .cnf 结尾,建议以 z_ 开头(如 z_sql_mode.cnf)以保证最后加载、覆盖其他配置。


3. 常见 sql_mode 配置示例

  • MySQL 8.0 默认模式(严格、安全):
    1. sql_mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
  • 去掉 ONLY_FULL_GROUP_BY(解决常见的 GROUP BY 报错):
    1. sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
  • 彻底放宽模式(不推荐生产环境使用):
    1. sql_mode=''

4. 修改后必须执行的操作

保存文件后,重启 MySQL 服务使配置生效:

  1. sudo systemctl restart mysql
  2. # 或者
  3. sudo service mysql restart

5. 验证是否生效

登录 MySQL 命令行,执行:

  1. SELECT @@sql_mode;

如果输出结果中包含你刚设置的模式,说明配置成功。


💡 补充:临时修改(无需重启,重启后失效)

如果你只是想临时测试,可以登录 MySQL 后执行:

  1. -- 全局生效(当前 MySQL 实例运行期间有效)
  2. SET GLOBAL sql_mode='STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION';
  3. -- 当前会话生效
  4. SET SESSION sql_mode='STRICT_TRANS_TABLEES,NO_ENGINE_SUBSTITUTION';