欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答
作者:郑仕兵
万里数据库DBA,擅长数据库备份恢复、异构数据库间数据迁移,对开源数据库相关技术有浓厚兴趣。
背景
在一台旧的 centos 7 服务器上面新安装了 mysql 8.0.19,使用下面的初始化命令
mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --lower-case-table-names=1 --datadir=/data/mysql
初始化且启动成功后,使用命令mysql -S /data/mysql/mysql.sock 用于登录实例 做其他操作,遇到故障。
定位过程:
在只使用 socket 无法登陆数据库的情况下,做了如下测试
mysql -S /data/mysql/mysql.sock -- 无法登陆返回报错
mysql --defaults-file=/data/mysql/my.cnf -- 正常登陆数据库
mysql -S /data/mysql/mysql.sock -p -- 然后连续两个回车,可以正常登陆数据库(第一个回车提示输入密码,第二个回车为确认输入空密码)
按照正常理解,上面三种方式没有本质区别,但是只有第一种无法登陆数据库就比较奇怪,第 2、3 种方式可以登录数据库进行正常的操作,说明数据库是正常运行的。
在没有头绪的情况下,对第一种和第二种做了 strace 跟踪获取日志,对比日志差异,命令如下
strace -T -tt -s 200 -o strace_socket.log mysql -S /data/mysql/mysql.sock
strace -T -tt -s 200 -o strace_cnf.log mysql --defaults-file=/data/mysql/my.cnf
在对比两个 strace 日志的时候,发现如下区别 strace_socket.log 日志中,登录过程依次尝试打开文件
/etc/my.cnf
/etc/my.cnf.d/mysql-clients.cnf
/etc/mysql/my.cnf
/usr/local/mysql/etc/my.cnf
/root/.my.cnf
并且在打开/root/.my.cnf 中有获取到 user 和 password 的信息
而在 strace_cnf.log 日志中,登录过程依次尝试打开的文件仅仅为
/data/mysql/my.cnf
/root/.mylogin.cnf
而且并没有获取到相关的 user 和 password 信息
通过日志文件 strace_socket.log 中提示的信息,在服务器上面确实找到了文件/root/.my.cnf,其内容如下,而内容中的 user 和 password 正是 strace 日志中获取到的内容
为什么在使用 socket 登录的时候,会去寻找/root/.my.cnf 文件呢,经过官网文档的查找发现,mysql 默认会从下面的路径中从上往下寻找配置文件,如果其中有[client]域则会用于 mysql 客户端的登录使用,所以我们能够在 strace_socket.log 中发现 password=drACgwoqtM 的信息
作为验证,我将文件/root/.my.cnf 删除,再次使用 mysql -S /data/mysql/mysql.sock就可以正常登陆数据库了
至此问题原因定位清楚,问题得到解决,由于服务器上面有历史配置文件,导致新的实例连接读取了错误的配置文件,无法正常连接到数据库中。
后记
在定位过程中,查询初始化数据库–initialize-insecure 的时候发现,可以使用–skip-password,也能有效的避免这个问题,当密码为空时,官网建议使用该参数,而不是通过配置文件查找
整个问题解析,strace 非常快捷的发现了问题所在,这里简单介绍一下。
strace 是 Linux 环境下的一款程序调试工具,用来监测一个应用程序所使用的系统调用。Strace 是一个简单的跟踪系统调用执行的工具。在其最简单的形式中,它可以从开始到结束跟踪二进制的执行,并在进程的生命周期中输出一行具有系统调用名称,每个系统调用的参数和返回值的文本行。
常用参数:
-T:strace 输出显示时间
-t:可以在每行的输出之前添加时间戳,
-tt 可以精确到微妙级别,
-ttt 也可以精确到微妙级,但是它并不是打印当前时间,而是显示自从 epoch 以来的所经过的秒数
-s:指定输出的字符串的最大长度,默认为 32,如果输出到文件的话会全部输出
-o:指定将 strace 输出到文件
-ff:如果提供-o filename,则所有进程的跟踪结果输出到相应的 filename.pid中,pid 是各进程的进程号.
-e:指定跟踪某个行为,例如-e trace=open 指定只跟踪 open 行为
-y:将文件句柄用文件路径代替显示
简单使用举例
strace -T -tt -o /tmp/strace.log CMD
strace -T -tt CMD 2>&1 |tee /tmp/strace.log
strace -T -tt -s 200 -o /tmp/strace.log CMD
strace -T -tt -s 200 -ff -o /tmp/strace.log CMD
strace -T -tt -s 200 -e trace=XXXX -o /tmp/strace.log CMD
Enjoy GreatSQL :)