当前位置:首页 > 问答 > 正文

MySQL报错提示需要root权限,远程帮忙修复这类问题经验分享

前段时间,我在一个技术社群里看到一位网名叫“运维小菜鸟”的朋友发帖求助,他说他自己管理的测试服务器上的MySQL数据库突然连不上了,用命令行登录时,屏幕上弹出了一个他看不懂的错误信息,大概意思是“Access denied for user 'root'@'localhost'”,他尝试了知道的几个密码都失败了,急得团团转,因为上面有一些重要的测试数据,开发团队还等着用。

我当时正好有空,就问他能不能让我远程看一眼,在获得他同意并确保服务器可以通过SSH安全连接后,我让他分享了一个临时的高权限账号给我,连接上服务器后,我首先做的不是直接去动MySQL,而是让他回忆一下最近对这台服务器做过什么改动,这是我从一位老工程师那里学来的习惯,他总说“八成的问题都是最近的变化引起的”。“运维小菜鸟”想了一会儿说,大概一天前,他好像为了安全起见,运行过一个什么脚本,说是能优化MySQL的安全设置。

听到这里,我心里大概有数了,我让他带我找到那个脚本文件,打开一看,果然,这个脚本里包含了一条命令,是强制要求MySQL进行权限重置的,类似于mysql_secure_installation脚本会做的事情,问题很可能就出在这里:这个脚本可能重置了root用户的密码,或者改变了root用户的认证方式,而“运维小菜鸟”自己并不知道新密码是什么,或者他还在用旧密码尝试登录。

MySQL报错提示需要root权限,远程帮忙修复这类问题经验分享

我的思路很明确:既然本地都访问不了,那就必须想办法“绕过”MySQL的权限验证,强行进入系统,然后再重置密码,我记得在MySQL的官方文档的“故障排查”章节里提到过一种方法,就是通过在启动命令后面加上--skip-grant-tables这个参数来启动MySQL服务,这个参数的作用,用大白话讲,就是告诉MySQL:“这次启动,你先别管什么用户名密码了,让所有人都能进来。”

我让“运维小菜鸟”先停止当前的MySQL服务,他用的操作系统是CentOS,所以用的是systemctl stop mysqld命令,停止之后,我指导他使用mysqld_safe --skip-grant-tables &这个命令在后台以跳过权限表的方式启动MySQL服务,这个时候,我们再尝试用mysql -u root命令登录,果然,不需要密码就直接进去了,成功连接到了MySQL的命令行界面。

MySQL报错提示需要root权限,远程帮忙修复这类问题经验分享

进去之后,虽然拥有了最高权限,但因为跳过了权限验证,有些操作还是会受限,所以我们需要先把权限表重新加载进来,我让他依次执行以下SQL命令:

  1. flush privileges; 这个命令让MySQL重新加载权限表。
  2. 然后就可以修改root密码了,由于MySQL版本是5.7,我们使用了ALTER USER 'root'@'localhost' IDENTIFIED BY 'MyNewPass';这样的语句来设置一个新密码,这里我特别提醒他,要把'MyNewPass'换成一个他自己知道的、足够复杂的密码,并且要记牢。
  3. 执行完修改命令后,再执行一次flush privileges;确保修改生效。

密码修改成功后,我们退出了MySQL命令行,接下来是关键的一步:恢复正常启动,我们先是停掉了那个用--skip-grant-tables参数启动的MySQL进程,然后像平常一样,使用systemctl start mysqld命令正常启动MySQL服务。

服务启动后,最紧张的测试来了,我们使用mysql -u root -p命令,然后输入刚刚设置的新密码,屏幕上顺利显示出了MySQL的欢迎信息和提示符,登录成功了!“运维小菜鸟”在远程那头非常高兴,连声道谢。

这件事之后,我和他总结了一下经验,在对生产环境或重要测试环境进行任何修改,尤其是运行来历不明的脚本之前,一定要先备份,不仅是备份数据,最好对整个系统做个快照,遇到这种权限问题不要慌,MySQL提供了这种“安全模式”(指--skip-grant-tables)的进入方式,是解决问题的金钥匙,修改完密码后,一定要记得重启服务到正常模式,否则会留下巨大的安全漏洞,这次远程协助也算是有惊无险,顺利解决了。