MySQL root密碼忘記後更優雅的解決方法
前言
一直以來,對於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。
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對我們的支援。