MySQL 5.7 引入重大安全架構變更:user 表移除 Password 欄位,改用 authentication_string;新增密碼過期機制;預設啟用 validate_password 插件。導致舊版教學 (UPDATE user SET Password=...) 完全失效。本文提供經生產環境驗證的標準修改流程。
Password → authentication_stringpassword_expired 欄位控制,預設可能為 'Y'mysql_native_password,8.0 改為 caching_sha2_passwordvalidate_password,需符合長度、大小寫、數字、特殊字元要求mysql -u root -p
# 輸入舊密碼
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewPass123!';
# 或指定插件 (相容舊客戶端)
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'NewPass123!';
Query OK, 0 rows affected (0.01 sec)
此為最簡單、推薦方式。若密碼策略報錯,調整 validate_password_policy 或提高密碼複雜度。
# systemd 系統
systemctl stop mysqld
# 或 SysVinit
service mysqld stop
# 或強制終止 (不推薦常用)
killall -TERM mysqld
# 前台執行 (方便觀察日誌,新開終端機操作後續步驟)
mysqld_safe --skip-grant-tables &
# 生產環境建議加上 --skip-networking 禁止遠程連線
mysqld_safe --skip-grant-tables --skip-networking &
mysql -u root
# 無需密碼直接進入
mysql> USE mysql;
# 關鍵:更新 authentication_string 並解除過期
UPDATE user SET authentication_string=PASSWORD('NewPass123!'), password_expired='N' WHERE User='root' AND Host='localhost';
FLUSH PRIVILEGES;
QUIT;
# 終止 skip-grant-tables 進程
killall -TERM mysqld
# 正常啟動
systemctl start mysqld
# 或
mysqld_safe &
mysql -u root -p'NewPass123!'
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewPass123!';
# 再次確認 (可選)
SELECT User, Host, plugin, authentication_string, password_expired FROM user WHERE User='root';
為何需要步驟 5? MySQL 5.7 密碼過期機制要求首次登入後必須透過 ALTER USER 重新設定密碼,才能正式啟用帳號所有權限。僅更新 authentication_string 不足夠。
-- 暫時降低密碼策略 (需 SUPER 權限)
SET GLOBAL validate_password_policy=LOW;
SET GLOBAL validate_password_length=4;
-- 修改密碼
ALTER USER 'root'@'localhost' IDENTIFIED BY 'simple';
-- 恢復策略
SET GLOBAL validate_password_policy=MEDIUM;
SET GLOBAL validate_password_length=8;
或直接設定符合預設策略 (MEDIUM, 長度 8) 的強密碼:Str0ngP@ssw0rd!
| 錯誤訊息 | 原因 | 解決 |
|---|---|---|
| ERROR 1820 (HY000): You must SET PASSWORD | 密碼過期,未執行 ALTER USER | 登入後執行 ALTER USER ... IDENTIFIED BY ... |
| ERROR 1819 (HY000): Your password does not satisfy the current policy requirements | 密碼不符合 validate_password 策略 | 提高複雜度或暫時降低策略 |
| ERROR 1396 (HY000): Operation ALTER USER failed for 'root'@'localhost' | 帳號不存在或 Host 不匹配 | 檢查 SELECT User, Host FROM user; 確認精確匹配 |
| Unknown column 'Password' in 'field list' | 使用舊版 UPDATE ... SET Password=... 語法 | 改用 authentication_string 或 ALTER USER |
#!/bin/bash
# reset_mysql_root.sh - 需 root 權限執行
NEW_PASS="Str0ngP@ssw0rd!$(date +%s)"
systemctl stop mysqld
mysqld_safe --skip-grant-tables --skip-networking &
sleep 3
mysql -u root -e "USE mysql; UPDATE user SET authentication_string=PASSWORD('$NEW_PASS'), password_expired='N' WHERE User='root' AND Host='localhost'; FLUSH PRIVILEGES;"
killall -TERM mysqld
sleep 2
systemctl start mysqld
sleep 3
mysql -u root -p"$NEW_PASS" -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '$NEW_PASS';"
echo "Root password reset to: $NEW_PASS"
PASSWORD() 函式移除,skip-grant-tables 下無法用 PASSWORD(),需用 ALTER USER 或直接寫入 authentication_string (不建議手動寫入雜湊)。caching_sha2_password,舊版客戶端 (PHP mysqlnd < 7.4、舊 JDBC) 可能連不上,需指定 mysql_native_password。MySQL 5.7 修改 root 密鑰路徑:**知密碼 → ALTER USER**;**忘密碼 → stop → skip-grant-tables → UPDATE authentication_string + password_expired='N' → restart → ALTER USER**。牢記 authentication_string 欄位名與 password_expired 解除過期,避開舊教學陷阱。