当前位置: 首页 > 科技观察

MySQL客户端读取配置文件的顺序

时间:2023-03-16 16:34:21 科技观察

1.场景现象我在本地测试的时候,发现一个奇怪的现象。当我使用socket登录数据库时,发现没有指定用户,默认没有使用root用户。登录,却改成zhenxing用户。[root@10-186-61-162~]#mysql-S/data/mysql/3306/data/mysqld.sock-p输入密码:ERROR1045(28000):拒绝用户'zhenxing'@'127.0.0.1访问'(usingpassword:NO)通过观察当前mysql客户端的默认参数行为,可以看到与报错一致,默认用户确实改为了zhenxing。[root@10-186-61-162~]#mysql--help|egrep"user|host|port"-h,--host=name连接到主机。-P,--port=#用于连接的端口号或默认为0,在-u,--user=name登录的用户如果不是当前user.host127.0.0.1port3306userzhenxing这里是DBA,我们的第一反应肯定是查看/etc/my.cnf文件中是否配置了默认用户,于是查看配置文件的client配置参数,如下[client]host=127.0.0.1user=rootport=3306[mysql]host=127.0.0.1user=rootport=3306prompt='\U[\d]>'发现配置文件中的配置值为root用户,并没有配置zhenxing用户。好像没有读取这个配置文件,是不是读取了其他的配置文件?好了,继续查看其他配置文件。二、排查思路1、获取配置文件的读取顺序我们先打印出所有可能的配置文件及其读取顺序,一一核对。##查看mysql客户端读取配置文件的顺序[root@10-186-61-162~]#mysql--verbose--help|grepmy.cnforderofpreference,my.cnf,$MYSQL_TCP_PORT,/etc/my.cnf/etc/mysql/my.cnf/usr/local/mysql/etc/my.cnf/data/mysql/3306/base/my.cnf~/.my.cnf2,检查/etc/my.cnf/etc/my.cnf已经确认之前没有做过相关配置,这里略过。3、查看/etc/mysql/my.cnf查看/etc/mysql/my.cnf配置,发现没有相关配置,排除即可。[root@10-186-61-162~]#cat/etc/mysql/my.cnfcat:/etc/mysql/my.cnf:Nosuchfileordirectory4.查看/usr/local/mysql/etc/my.cnf查看/usr/local/mysql/etc/my.cnf配置,发现没有相关配置,排除即可。[root@10-186-61-162~]#cat/usr/local/mysql/etc/my.cnfcat:/usr/local/mysql/etc/my.cnf:Nosuchfileordirectory5.检查/data/mysql/3306/base/my.cnf查看/data/mysql/3306/base/my.cnf配置,发现没有相关配置,排除。[root@10-186-61-162~]#cat/data/mysql/3306/base/my.cnfcat:/data/mysql/3306/base/my.cnf:Nosuchfileordirectory6.检查~/.my.cnf检查~/.my.cnf仍然不存在相关配置,排除。[root@10-186-61-162~]#cat~/.my.cnfcat:/root/.my.cnf:Thereisnosuchfileordirectorysofargetting根据mysql--verbose--help|grepmy.cnf排除配置文件读取路径,未配置用户zhenxing。7、使用no-defaults消除配置文件干扰尝试使用--no-defaults而不读取任何配置文件来消除配置文件干扰,看是否恢复正常。[root@10-186-61-162~]#mysql--help|grepno-defaults--no-defaultsDon'treaddefaultoptionsfromanyoptionfile##查看配置文件时客户端的默认选项未读取值[root@10-186-61-162~]#mysql--no-defaults--help|egrep"user|host|port"-h,--host=name连接到主机。-P,--port=#用于连接的端口号或默认为0,在-u,--user=name登录的用户如果不是当前user.host127.0.0.1port3306userzhenxing##查看所有客户端配置fileparametersreadset[root@10-186-61-162~]#mysql--print-defaultsmysql将使用以下参数启动:--host=127.0.0.1--user=root--port=3306--host=127.0.0.1--user=root--port=3306--prompt=\U[\d]>--user=zhenxing--password=*****--host=127.0.0.1--port=3306从上面的输出结果,我们可以得到以下两个基本现象:即使指定了--no-defaults,没有读取配置文件,这个用户的默认值依然是zhenxing。当输出--print-defaults得到实际运行时设置的值时,可以看到/etc/my.cnf下的【client】,以及【mysql】标签下的属性配置从上到下正确获取除了/etc/my.cnf,最后还有4个参数--user=zhenxing--password=*****--host=127.0.0.1--port=3306在命令末尾额外添加了ps:从mysql客户端和服务端读取配置的原则是从上到下读取文件,相同的参数配置后面会覆盖前面的参数。经过一系列的排除,还是没有找到默认值。修改来源8.打印mysql客户端的系统调用。使用strace可以直接观察mysql客户端在执行过程中调用了哪些配置。以下是调用我的相关配置的片段。"/etc/my.cnf",{st_mode=S_IFREG|0644,st_size=195,...})=0=32.stat("/etc/mysql/my.cnf",0x7ffd56813180)=-1ENOENT(没有这样的文件或目录)3。stat("/usr/local/mysql/etc/my.cnf",0x7ffd56813180)=-1ENOENT(没有那个文件或目录)4。stat("/data/mysql/3306/base/my.cnf",0x7ffd56813180)=-1ENOENT(没有那个文件或目录)5。stat("/root/.my.cnf",0x7ffd56813180)=-1ENOENT(没有那个文件或目录)6。stat("/root/.mylogin.cnf",{st_mode=S_IFREG|0600,st_size=336,...})=0通过上面的调用顺序,我们可以得到如下结论:第1行的调用顺序-5和我们验证的一样逻辑基本一致。第2-5行显示为Nosuchfileordirectory,这与我们的验证结果是一致的。第6行的输出增加了对/root/.mylogin.cnf的读操作,我们可以知道当前文件确实存在9.查看/root/.mylogin.cnf我们一般看到这个文件就知道了,这是我的sql_config_editor工具用于配置login-path的生成文件,我们可以通过以下方式查看当前的配置信息[root@10-186-61-162~]#mysql_config_editorprint--all[client]user="zhenxing"password=*****host="127.0.0.1"port=3306这里可以看到配置中有client标签的连接参数配置。配置的内容正是我们文章开头展示的异常默认值。至此我们基本上已经找到了造成这种奇怪现象的原因。出现这种故障场景的原因是本机在测试环境做了一些mysql_config_editor的使用测试,导致出现这种现象。mysql--verbose--help|grepmy.cnf除了mysql输出的常规顺序读取配置外,最后还会额外读取.mylogin.cnf文件中的配置。2、即使指定了--no-defaults,仍然会读取.mylogin.cnf中[client]和[mysql]标签的配置值。其中,官方文档在以下链接中也给出了明确的说明(以下为重点说明片段)。https://dev.mysql.com/doc/refman/8.0/en/option-file-options.htmlmysql客户端从其他选项文件中读取[client]和[mysql],以及[client]、[mysql]和[mypath]来自登录路径文件。即使使用--no-defaults选项,客户端程序也会读取登录路径文件。这允许以比命令行更安全的方式指定密码,即使存在--no-defaults也是如此。我个人猜测,当时这样设计的目的是考虑到备份脚本等需要连接数据库时,为了防止不必要的参数文件的干扰,.mylogin.cnf文件仍然可以在指定配置的--no-defaults参数加密密码后使用以提高安全性。