MySQL8.0 雙密碼機制:解決應用程序用戶不停機修改密碼問題
在數據庫管理中,定期更新密碼是確保系統安全的重要手段。然而,如何在不影響現有連接的情況下平滑地切換密碼,避免系統停機,始終是一個挑戰。MySQL 8.0 引入的“雙密碼”機制為這種需求提供了有效的解決方案,使得密碼更新過程能夠無縫進行。
1. MySQL8.0雙密碼特性
自 MySQL 8.0.14 版本起,MySQL 支持為每個用戶賬戶設置兩個密碼:主密碼(新密碼)和輔助密碼(舊密碼)。這種雙密碼機制能夠在一些復雜的系統中,特別是當涉及大量 MySQL 實例、復制、多個應用程序連接以及頻繁的密碼更新時,保持服務不中斷,從而實現更流暢的密碼更改流程。
常見使用場景:
- 系統有多個 MySQL 服務器,其中一些可能是主從復制。
- 不同的應用程序連接到不同的 MySQL 服務器。
- 系統需要定期更新連接憑據,且不希望中斷現有服務。
如果不使用雙密碼機制,密碼更改可能需要仔細協調更新過程,以避免在某些服務器或應用程序上造成停機或連接中斷。而通過雙密碼機制,可以在不影響現有連接的情況下分階段完成憑據更新,從而避免停機。
2. 雙密碼機制的工作流程
(1)為賬戶添加新密碼并保留舊密碼
在更改密碼時,首先通過 RETAIN CURRENT PASSWORD 子句設置新的主密碼,并保留當前密碼作為輔助密碼。此時,客戶端可以繼續使用舊密碼(輔助密碼)連接數據庫,同時新密碼(主密碼)也已經生效,主要語法如下:
ALTER USER 'user'@'host'
IDENTIFIED BY 'new_password'
RETAIN CURRENT PASSWORD;
該命令會將 new_password 設置為主密碼,并將舊密碼保留為輔助密碼。此時,
無論是使用新密碼還是舊密碼的客戶端,都能正常連接到數據庫。
案例如下:
# 創建一個用戶并設定密碼
mysql> create user 'app_user'@'localhost' identified by '123456';
Query OK, 0 rows affected (0.03 sec)
mysql> grant select on *.* to 'app_user'@'localhost';
Query OK, 0 rows affected, 1 warning (0.01 sec)
# 登錄測試密碼
[root@alidb ~]# /usr/local/mysql8.0/bin/mysql -uapp_user -p'123456' --socket=/data//mysql/mysql3308/tmp/mysql.sock
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 24090
Server version: 8.0.39 MySQL Community Server - GPL
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> select user();
+--------------------+
| user() |
+--------------------+
| app_user@localhost |
+--------------------+
1 row in set (0.00 sec)
原密碼可以正常登錄。
再創建新密碼進行驗證。
#創建新密碼
mysql> ALTER USER 'app_user'@'localhost' IDENTIFIED BY 'Test@123456' RETAIN CURRENT PASSWORD;
Query OK, 0 rows affected (0.01 sec)
# 使用新密碼登錄
[root@alidb ~]# /usr/local/mysql8.0/bin/mysql -uapp_user -p'Test@123456' --socket=/data//mysql/mysql3308/tmp/mysql.sock
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 24093
Server version: 8.0.39 MySQL Community Server - GPL
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> select user();
+--------------------+
| user() |
+--------------------+
| app_user@localhost |
+--------------------+
1 row in set (0.00 sec)
mysql>
mysql> exit
Bye
# 再次使用原密碼登錄
[root@alidb ~]# /usr/local/mysql8.0/bin/mysql -uapp_user -p'123456' --socket=/data//mysql/mysql3308/tmp/mysql.sock
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 24094
Server version: 8.0.39 MySQL Community Server - GPL
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> select user();
+--------------------+
| user() |
+--------------------+
| app_user@localhost |
+--------------------+
1 row in set (0.00 sec)
可見,新密碼及原密碼均可以登錄。
(2)廢棄舊密碼
當新密碼已經在所有服務器上同步,且所有應用程序也更新為使用新密碼時,可以使用 DISCARD OLD PASSWORD 子句來丟棄輔助密碼(原密碼),使得數據庫僅接受主密碼(新密碼)。例如:
ALTER USER 'app_user'@'localhost' DISCARD OLD PASSWORD;
此時,客戶端只能使用主密碼進行連接,舊密碼(輔助密碼)將不再有效。
# 新密碼登錄
root@alidb ~]# /usr/local/mysql8.0/bin/mysql -uapp_user -p'Test@123456' --socket=/data//mysql/mysql3308/tmp/mysql.sock
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 24099
Server version: 8.0.39 MySQL Community Server - GPL
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> select user();
+--------------------+
| user() |
+--------------------+
| app_user@localhost |
+--------------------+
1 row in set (0.00 sec)
mysql> exit
Bye
#原密碼無法登錄了
[root@alidb ~]# /usr/local/mysql8.0/bin/mysql -uapp_user -p'123456' --socket=/data//mysql/mysql3308/tmp/mysql.sock
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'app_user'@'localhost' (using password: YES)
3.小結
MySQL 8.0 的雙密碼機制為數據庫管理員提供了一個無縫過渡的方式,使得密碼更新過程可以分階段進行,避免了傳統方式中可能造成的停機和連接中斷問題。通過這種機制,DBA可以在不影響系統可用性的前提下,安全地執行密碼更新操作。