MySQL root密码忘记后更优雅的解决方法
前言
一直以来,对于MySQLroot密码的忘记,以为只有一种解法-skip-grant-tables。
问了下群里的大咖,第一反应也是skip-grant-tables。通过搜索引擎简单搜索了下,无论是百度,抑或Google,只要是用中文搜索,首页都是这种解法。可见这种解法在某种程度上已经占据了使用者的心智。下面具体来看看。
skip-grant-tables的解法
首先,关闭实例
这里,只能通过killmysqld进程的方式。
注意:不是mysqld_safe进程,也切忌使用kill-9。
#ps-ef|grepmysqld root62206171008:14pts/000:00:00/bin/shbin/mysqld_safe--defaults-file=my.cnf mysql63476220008:14pts/000:00:01/usr/local/mysql57/bin/mysqld--defaults-file=my.cnf--basedir=/usr/local/mysql57--datadir=/usr/local/mysql57/data--plugin-dir=/usr/local/mysql57/lib/plugin--user=mysql--log-error=slowtech.err--pid-file=slowtech.pid--socket=/usr/local/mysql57/data/mysql.sock--port=3307 root64186171008:17pts/000:00:00grep--color=automysqld #kill6347
使用--skip-grant-tables参数,重启实例
#bin/mysqld_safe--defaults-file=my.cnf--skip-grant-tables--skip-networking&
设置了该参数,则实例在启动过程中会跳过权限表的加载,这就意味着任何用户都能登录进来,并进行任何操作,相当不安全。
建议同时添加--skip-networking参数。其会让实例关闭监听端口,自然也就无法建立TCP连接,而只能通过本地socket进行连接。
MySQL8.0就是这么做的,在设置了--skip-grant-tables参数的同时会自动开启--skip-networking。
修改密码
#mysql-S/usr/local/mysql57/data/mysql.sock mysql>updatemysql.usersetauthentication_string=password('123456')wherehost='localhost'anduser='root'; QueryOK,0rowsaffected,1warning(0.00sec) Rowsmatched:1Changed:0Warnings:1 mysql>flushprivileges; QueryOK,0rowsaffected(0.00sec)
注意:
这里的update语句针对的是MySQL5.7的操作,如果是在5.6版本,修改的应该是password字段,而不是authentication_string。
updatemysql.usersetpassword=password('123456')wherehost='localhost'anduser='root';
而在MySQL8.0.11版本中,这种方式基本不可行,因为其已移除了PASSWORD()函数及不再支持SETPASSWORD...=PASSWORD('auth_string')语法。
不难发现,这种方式的可移植性实在太差,三个不同的版本,就先后经历了列名的改变,及命令的不可用。
下面,介绍另外一种更通用的做法,还是在skip-grant-tables的基础上。
与上面不同的是,其会先通过flushprivileges操作触发权限表的加载,再使用alteruser语句修改root用户的密码,如:
#bin/mysql-S/usr/local/mysql57/data/mysql.sock mysql>alteruser'root'@'localhost'identifiedby'123'; ERROR1290(HY000):TheMySQLserverisrunningwiththe--skip-grant-tablesoptionsoitcannotexecutethisstatement mysql>flushprivileges; QueryOK,0rowsaffected(0.00sec) mysql>alteruser'root'@'localhost'identifiedby'123'; QueryOK,0rowsaffected(0.00sec)
免密码登录进来后,直接执行alteruser操作是不行的,因为此时的权限表还没加载。可先通过flushprivileges操作触发权限表的加载,再执行alteruser操作。
需要注意的是,通过alteruser修改密码只适用于MySQL5.7和8.0,如果是MySQL5.6,此处可写成
updatemysql.usersetpassword=password('123456')wherehost='localhost'anduser='root';
最后重启实例
mysql>shutdown; #bin/mysqld_safe--defaults-file=my.cnf&
需要注意的是,如果在启动的过程中没有指定--skip-networking参数,无需重启实例。但在网上看到的绝大多数方案,都是没有指定该参数,但重启了实例,实在没有必要。
下面对这个方案做个总结:
1.如果只添加了--skip-grant-tables,修改完密码后,其实无需重启,执行flushprivileges即可。
2.从安全角度出发,建议加上--skip-networking。但因其是静态参数,将其剔除掉需要重启实例。
3.加上--skip-networking,虽然可以屏蔽掉TCP连接,但对于本地其它用户,只要有socket文件的可读权限,都能无密码登录。还是存在安全隐患。
4.不建议通过update的方式修改密码,更通用的其实是alteruser。
更优雅的解法
相对于skip-grant-tables方案,我们来看看另外一种更优雅的解法,其只会重启一次,且基本上不存在安全隐患。
首先,依旧是关闭实例
其次,创建一个sql文件
写上密码修改语句
#viminit.sql alteruser'root'@'localhost'identifiedby'123456';
最后,使用--init-file参数,启动实例
#bin/mysqld_safe--defaults-file=my.cnf--init-file=/usr/local/mysql57/init.sql&
实例启动成功后,密码即修改完毕~
如果mysql实例是通过服务脚本来管理的,除了创建sql文件,整个操作可简化为一步。
#servicemysqldrestart--init-file=/usr/local/mysql57/init.sql
注意:该操作只适用于/etc/init.d/mysqld这种服务管理方式,不适用于RHEL7新推出的systemd。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。