MySQL启动配置文件搜索顺序解析

引言

MySQL数据库支持从配置文件中读取启动选项,不用每次启动时在命令行输入,方便管理。很多选项都是以纯文本的形式存在,可以用任何的编辑器打开编辑。.mylogin.cnf文件除外,此文件包含了登录路径的选项,使用mysql_config_editor程序去创建的加密文件。

搜索顺序

MySQL默认情况下是按照一定的顺序去搜索具体路径的配置文件,并且在windows和linux的操作顺序不一样。
搜索顺序,按照下面表格中文件名从上往下,如果存在相同的选项,最后一个出现的选项有最高的优先级。参考官网的解释:”Options are processed in order, so if an option is specified multiple times, the last occurrence takes precedence.”

Windows

在windows上,MySQL按照指定的顺序从下表中显示的文件中读取启动选项

文件名 描述
%WINDIR%\my.ini, %WINDIR%\my.cnf 全局
C:\my.ini, C:\my.cnf 全局
BASEDIR\my.ini, BASEDIR\my.cnf 全局
defaults-extra-file 如果存在—default-extra-file
%APPDATA%\MySQL.mylogin.cnf Login选项,仅适用于client
1
2
3
4
其中,
WINDIR表示Windows目录的位置,例如C:\Windows
APPDIR表示Windows应用程序数据目录
BASEDIR表示MySQL的安装目录

Linux or Unix

在Linux或Unix等类Unix系统上,MySQL按照指定的顺序从下表中显示的文件中读取启动选项

文件名 描述
/etc/my.cnf 全局
/etc/mysql/my.cnf 全局
SYSCONFDIR/my.cnf 全局
$MYSQL_HOME/my.cnf 仅适用于server
defaults-extra-file 如果存在—default-extra-file
~/.my.cnf 用户的选项
~/.mylogin.cnf Login选项,仅适用于client
1
2
3
4
其中,
~表示当前用户的主目录
SYSCONFIGDIR表示在构建MySQL时使用SYSCONFIGDIR选项CMake的指定目录
MySQL_HOME是一个环境变量,如果没有设置,并使用mysqld_safe启用MySQL,这时MySQL的安装目录就是其BASEDIR

实验

生产环境一般多使用linux系统,在单实例和多实例启动时,my.cnf加载的顺序也存在不一样的情况,这里分别进行测试,对结果进行说明

单实例

在不考虑SYSCONDIR,同时BASEDIR为/usr/local/mysql的情况下,从上面的搜索顺序来看,MySQL会依次加载以下的文件:

  • /etc/my.cnf
  • /etc/mysql/my.cnf
  • /usr/local/mysql/my.cnf
  • ~/.my.cnf
    也就是说MySQL会找/etc/my.cnf这个文件,如果此文件不存在,继续找/etc/mysql/my.cnf这个文件,依此类推,最后是读取–defaults-file加载的文件,如果最后的文件也不存在,通过mysqld的帮助可以看出来:

image

/etc/my.cnf

当没有指定–defaults-file时,而且/etc/my.cnf,/etc/mysql/my.cnf,/usr/local/mysql/my.cnf,~/.my.cnf中只存在/etc/my.cnf时,很明显MySQL是加载的/etc/my.cnf

image

/etc/my.cnf && /etc/mysql/my.cnf

当没有指定–defaults-file时,而且/etc/my.cnf,/etc/mysql/my.cnf,/usr/local/mysql/my.cnf,~/.my.cnf中只存在/etc/my.cnf和/etc/mysql/my.cnf时,很明显MySQL是加载的/etc/mysql/my.cnf

image

/etc/my.cnf && /etc/mysql/my.cnf && /usr/local/mysql/my.cnf

当没有指定–defaults-file时,而且/etc/my.cnf,/etc/mysql/my.cnf,/usr/local/mysql/my.cnf,~/.my.cnf中存在/etc/my.cnf和/etc/mysql/my.cnf和/usr/local/mysql/my.cnf时,很明显MySQL是加载的/usr/local/mysql/my.cnf

image

/etc/my.cnf && /etc/mysql/my.cnf && /usr/local/mysql/my.cnf && ~/.my.cnf

当没有指定–defaults-file时,而且/etc/my.cnf,/etc/mysql/my.cnf,/usr/local/mysql/my.cnf,~/.my.cnf全部存在时,很明显MySQL是加载的~/my.cnf

image

defaults-file

当指定–defaults-file为/tmp/my.cnf时,而且/etc/my.cnf,/etc/mysql/my.cnf,/usr/local/mysql/my.cnf,~/.my.cnf全部存在时,很明显MySQL是加载的/tmp/my.cnf

image

多实例

多实例的启动通常使用mysqld_multi脚本,此脚本也支持–defaults-file选项。从mysqld_multi的官档上可以看出,mysqld_multi支持[mysqldN]的标签,其中N代表常量数字,此脚本是调用mysqld_safe命令是启动服务,所以支持[mysqld]标签做通用性配置文件,适用于多个实例启动时的通用配置,也可以使用[mysqldN],N代表特定端口做特殊性实例配置。

/etc/my.cnf && [mysqldN]

当没有指定–defaults-file时,而且/etc/my.cnf,/etc/mysql/my.cnf,/usr/local/mysql/my.cnf,~/.my.cnf全部存在时,同时在[mysqld]中全部配置innodb_lock_wait_timeout,又在/etc/my.cnf加了一个[mysqld3306]标签,这时候,MySQL是加载的是/etc/my.cnf的[mysqld3306]标签配置文件

image

/etc/my.cnf && /etc/mysql/my.cnf && [mysqldN]

当没有指定–defaults-file时,而且/etc/my.cnf,/etc/mysql/my.cnf,/usr/local/mysql/my.cnf,~/.my.cnf全部存在时,同时在[mysqld]中全部配置innodb_lock_wait_timeout,又在/etc/my.cnf和/etc/mysql/my.cnf加了一个[mysqld3306]标签,这时候,MySQL是加载的是/etc/mysql/my.cnf的[mysqld3306]标签配置文件

image

/etc/my.cnf && /etc/mysql/my.cnf &&/usr/local/mysql/my.cnf && [mysqldN]

当没有指定–defaults-file时,而且/etc/my.cnf,/etc/mysql/my.cnf,/usr/local/mysql/my.cnf,~/.my.cnf全部存在时,同时在[mysqld]中全部配置innodb_lock_wait_timeout,又在/etc/my.cnf和/etc/mysql/my.cnf和/usr/local/mysql/my.cnf加了一个[mysqld3306]标签,这时候,MySQL是加载的还是/etc/my.cnf的[mysqld3306]标签配置文件

image

/etc/my.cnf && /etc/mysql/my.cnf &&/usr/local/mysql/my.cnf && ~/.mycf && [mysqldN]

当没有指定–defaults-file时,而且/etc/my.cnf,/etc/mysql/my.cnf,/usr/local/mysql/my.cnf,~/.my.cnf全部存在时,同时在[mysqld]中全部配置innodb_lock_wait_timeout,又在全部配置了[mysqld3306]标签,这时候,MySQL是加载的是~/my.cnf的[mysqld3306]标签配置文件

image

defaults-file && [mysqldN]

指定–defaults-file为/tmp/my.cnf时,而且/etc/my.cnf,/etc/mysql/my.cnf,/usr/local/mysql/my.cnf,~/.my.cnf全部存在时,同时在了[mysqld]中全部配置innodb_lock_wait_timeout,又在全部配置了了[mysqld3306]标签,这时候,了MySQL是加载的是/tmp/my.cnf的[mysqld3306]标签配置文件

image

defaults-file

指定–defaults-file为/tmp/my.cnf时,而且/etc/my.cnf,/etc/mysql/my.cnf,/usr/local/mysql/my.cnf,~/.my.cnf全部存在时,同时在[mysqld]中全部配置innodb_lock_wait_timeout,全部未配置了[mysqld3306]标签,这时候,MySQL是加载的是~/my.cnf的配置文件而不是加载的/tmp/my.cnf的配置文件,说明mysqld_multi不加载除默认搜索的配置文件外的其他[mysqld]标签

image

启动方式

MySQL的启动包括多种,包括以下几种:

  • /usr/local/mysql/bin/mysqld –defaults-file=/etc/my.cnf –basedir=/usr/local/mysql –datadir=/opt/mysql/data –user=mysql
  • /usr/local/mysql/bin/mysqld_safe –defaults-file=/etc/my.cnf –basedir=/usr/local/mysql –datadir=/opt/mysql/data –user=mysql
  • /etc/init.d/mysqld start && service mysqld start
  • mysqld_multi start

    service mysqld start

    service mysqld start的启动有一个要注意的地方,它不会加载~/.my.cnf,实验如下,很明显,部service mysqld start启动方式不加载~/.my.cnf的参数

image

分析

1
由于linux的service启动服务的方式是调用的/sbin/service脚本来进行管理的,并且/sbin/service脚本是shell编写的,可以通过debug的模式来查看具体执行过程

image

1
2
3
4
5
通过上面的执行过程可以了解到,service mysqld start启动mysql的方式,实际最终调用的命令为:
env -i PATH=/sbin:/usr/sbin:/bin:/usr/bin TERM=linux SYSTEMCTL_IGNORE_DEPENDENCIES= SYSTEMCTL_SKIP_REDIRECT= /etc/init.d/mysqld start
此命令没有包含/home/mysql的环境变量,如果修改为以下命令,则可以加载~/.my.cnf
命令为:
env -i PATH=/sbin:/usr/sbin:/bin:/usr/bin HOME=/home/mysql TERM=linux SYSTEMCTL_IGNORE_DEPENDENCIES= SYSTEMCTL_SKIP_REDIRECT= /etc/init.d/mysqld start

解决方案

从脚本/sbin/service的最下面部分可以看出,具体的启动命令,如果想修改为让service mysqld start的启动方式也能搜索~/.my.cnf的参数,可以修改具体的脚本,添加了一个if else判断条件,如下:

1
2
3
4
5
6
7
8
9
将脚本/sbin/service的第81行的原始命令:
env -i PATH="$PATH" TERM="$TERM" SYSTEMCTL_IGNORE_DEPENDENCIES=${SYSTEMCTL_IGNORE_DEPENDENCIES} SYSTEMCTL_SKIP_REDIRECT=${SYSTEMCTL_SKIP_REDIRECT} "${SERVICEDIR}/${SERVICE}" ${ACTION} ${OPTIONS}
修改为
if [ "${SERVICE}" = "mysqld" ]; then
env -i PATH="$PATH" HOME=/home/mysql TERM="$TERM" SYSTEMCTL_IGNORE_DEPENDENCIES=${SYSTEMCTL_IGNORE_DEPENDENCIES} SYSTEMCTL_SKIP_REDIRECT=${SYSTEMCTL_SKIP_REDIREC
T} "${SERVICEDIR}/${SERVICE}" ${ACTION} ${OPTIONS}
else
env -i PATH="$PATH" TERM="$TERM" SYSTEMCTL_IGNORE_DEPENDENCIES=${SYSTEMCTL_IGNORE_DEPENDENCIES} SYSTEMCTL_SKIP_REDIRECT=${SYSTEMCTL_SKIP_REDIRECT} "${SERVICEDIR}/${SERVICE}" ${ACTION} ${OPTIONS}
fi

如下:

image

image
image

修改后的脚本启动一下测试,查看已经满足需求

image

mysqld_multi start

当mysqld_multi方式指定–defaults-file的参数文件时,不加载除默认搜索顺序以外的[mysqld]标签,也可以做下debug,mysqld_multi是perl脚本,可能通过perl -d script的方式进行调试,这里不再展示。

结论

通过以上的的测试,得出以下结论

1
2
3
4
1.	默认情况前三种启动方式下,[mysqld]标签以按照/etc/my.cnf,/etc/mysql/my.cnf,/usr/local/mysql/my.cnf,~/.my.cnf,--defaults-file搜索顺序加载
2. mysqld_mutli启动方式,[mysqldN]标签也是按照/etc/my.cnf,/etc/mysql/my.cnf,/usr/local/mysql/my.cnf,~/.my.cnf,--defaults-file搜索顺序加载。但是,[mysqld]标签只按照/etc/my.cnf,/etc/mysql/my.cnf,/usr/local/mysql/my.cnf,~/.my.cnf搜索顺序加载,不加载--defaults-file的配置
3. service mysqld start启动方式,默认不加载~/.my.cnf文件,需要修改脚本才能让其支持搜索
4. 当找不到/etc/my.cnf,/etc/mysql/my.cnf,/usr/local/mysql/my.cnf,~/.my.cnf,--defaults-file的配置时,默认编译的mysql,参数是全部其默认值,数据目录保存在BASEDIR下的data目录。比如,BASEDIR为/usr/local/mysql,则DATADIR为/usr/local/mysql/data,上面没有实验这一项

-------------本文结束感谢您的阅读-------------