阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

MySQL root密码忘记,原来还有更优雅的解法!

134次阅读
没有评论

共计 3073 个字符,预计需要花费 8 分钟才能阅读完成。

一直以来,对于 MySQL root 密码的忘记,以为只有一种解法 -skip-grant-tables。

问了下群里的大咖,第一反应也是 skip-grant-tables。通过搜索引擎简单搜索了下,无论是百度,抑或 Google,只要是用中文搜索,首页都是这种解法。可见这种解法在某种程度上已经占据了使用者的心智。下面具体来看看。

skip-grant-tables 的解法

首先,关闭实例

这里,只能通过 kill mysqld 进程的方式。

注意:不是 mysqld_safe 进程,也切忌使用 kill -9。

# ps -ef |grep mysqld
root      6220  6171  0 08:14 pts/0    00:00:00 /bin/sh bin/mysqld_safe –defaults-file=my.cnf
mysql      6347  6220  0 08:14 pts/0    00: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
root      6418  6171  0 08:17 pts/0    00:00:00 grep –color=auto mysqld

# kill 6347

使用 –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> update mysql.user set authentication_string=password(‘123456′) where host=’localhost’ and user=’root’;
Query OK, 0 rows affected, 1 warning (0.00 sec)
Rows matched: 1  Changed: 0  Warnings: 1

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

注意:

这里的 update 语句针对的是 MySQL 5.7 的操作,如果是在 5.6 版本,修改的应该是 password 字段,而不是 authentication_string。
update mysql.user set password=password(‘123456′) where host=’localhost’ and user=’root’;

而在 MySQL 8.0.11 版本中,这种方式基本不可行,因为其已移除了 PASSWORD() 函数及不再支持 SET PASSWORD … = PASSWORD (‘auth_string’) 语法。

不难发现,这种方式的可移植性实在太差,三个不同的版本,就先后经历了列名的改变,及命令的不可用。

下面,介绍另外一种更通用的做法,还是在 skip-grant-tables 的基础上。

与上面不同的是,其会先通过 flush privileges 操作触发权限表的加载,再使用 alter user 语句修改 root 用户的密码,如:

# bin/mysql -S /usr/local/mysql57/data/mysql.sock

mysql> alter user ‘root’@’localhost’ identified by ‘123’;
ERROR 1290 (HY000): The MySQL server is running with the –skip-grant-tables option so it cannot execute this statement

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

mysql> alter user ‘root’@’localhost’ identified by ‘123’;
Query OK, 0 rows affected (0.00 sec)

免密码登录进来后,直接执行 alter user 操作是不行的,因为此时的权限表还没加载。可先通过 flush privileges 操作触发权限表的加载,再执行 alter user 操作。

需要注意的是,通过 alter user 修改密码只适用于 MySQL5.7 和 8.0,如果是 MySQL 5.6,此处可写成

update mysql.user set password=password(‘123456′) where host=’localhost’ and user=’root’;

最后重启实例

mysql> shutdown;

# bin/mysqld_safe –defaults-file=my.cnf &

需要注意的是,如果在启动的过程中没有指定 –skip-networking 参数,无需重启实例。但在网上看到的绝大多数方案,都是没有指定该参数,但重启了实例,实在没有必要。

下面对这个方案做个总结:

1. 如果只添加了 –skip-grant-tables,修改完密码后,其实无需重启,执行 flush privileges 即可。

2. 从安全角度出发,建议加上 –skip-networking。但因其是静态参数,将其剔除掉需要重启实例。

3. 加上 –skip-networking,虽然可以屏蔽掉 TCP 连接,但对于本地其它用户,只要有 socket 文件的可读权限,都能无密码登录。还是存在安全隐患。

4. 不建议通过 update 的方式修改密码,更通用的其实是 alter user。

更优雅的解法

相对于 skip-grant-tables 方案,我们来看看另外一种更优雅的解法,其只会重启一次,且基本上不存在安全隐患。

首先,依旧是关闭实例

其次,创建一个 sql 文件

写上密码修改语句

# vim init.sql
alter user ‘root’@’localhost’ identified by ‘123456’;

最后,使用 –init-file 参数,启动实例

# bin/mysqld_safe –defaults-file=my.cnf –init-file=/usr/local/mysql57/init.sql &

实例启动成功后,密码即修改完毕~

如果 mysql 实例是通过服务脚本来管理的,除了创建 sql 文件,整个操作可简化为一步。

# service mysqld restart –init-file=/usr/local/mysql57/init.sql

注意:该操作只适用于 /etc/init.d/mysqld 这种服务管理方式,不适用于 RHEL 7 新推出的 systemd。

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-22发表,共计3073字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中