Root 密碼遺忘是 DBA/運維必遇場景。核心原理:**跳過權限表驗證 (Skip Grant Tables) 啟動實例 → 以 Root 免密登錄 → 更新 mysql.user 表密碼 → 刷新權限 → 正常重啟**。本文覆蓋 Windows、Linux (Systemd/SysVinit)、Docker、MySQL 5.7/8.0 版本差異的完整操作手冊,並給出生產環境安全操作規範。
MySQL 權限驗證流程:連接 → 線程創建 → 權限檢查 (mysql.user 表) → 授權。啟動參數 --skip-grant-tables 使服務器**跳過權限檢查階段**,允許任意用戶免密登錄並擁有所有權限 (相當於 Root)。**極度危險,必須在網絡隔離/防火牆封鎖下操作**。
# 1. 創建臨時 override 文件
systemctl edit mysqld
# 編輯器中輸入:
[Service]
ExecStart=
ExecStartPre=
ExecStart=/usr/sbin/mysqld --skip-grant-tables --skip-networking $MYSQLD_OPTS
# 保存退出 (會生成 /etc/systemd/system/mysqld.service.d/override.conf)
# 2. 重載配置並重啟
systemctl daemon-reload
systemctl restart mysqld
# 3. 免密登錄並重置密碼
mysql -u root
# 進入 MySQL 客戶端後:
# MySQL 5.7:
UPDATE mysql.user SET authentication_string=PASSWORD('NewStrongPass#2024!') WHERE User='root' AND Host='localhost';
FLUSH PRIVILEGES;
# MySQL 8.0 (authentication_string 列不再直接存密碼,需 ALTER USER):
ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewStrongPass#2024!';
FLUSH PRIVILEGES;
# 4. 移除 override 並正常重啟
systemctl revert mysqld # 刪除 override.conf
systemctl daemon-reload
systemctl restart mysqld
# 5. 驗證新密碼
mysql -u root -p'NewStrongPass#2024!' -e "SELECT VERSION();"
# 1. 編輯配置
vi /etc/my.cnf
[mysqld]
skip-grant-tables
skip-networking # 關鍵:禁止遠程連接,本地操作安全
# 2. 重啟
systemctl restart mysqld # 或 service mysqld restart
# 3. 登錄重置 (同方法 1 步驟 3)
# 4. 刪除配置項,重啟恢復正常
# 1. 停止服務
systemctl stop mysqld
# 2. 後台啟動跳過權限 (需保持終端或 nohup)
mysqld_safe --skip-grant-tables --skip-networking &
# 3. 新終端登錄重置
# 4. 正常關閉並啟動
mysqladmin -u root shutdown # 此時無需密碼
systemctl start mysqld
@rem 1. 以管理員身份打開 CMD / PowerShell
@rem 2. 停止服務
net stop mysql80 @rem 服務名可能為 MySQL80, MySQL57, mysqld
@rem 3. 跳過權限啟動 (控制台模式,窗口不能關閉)
cd "C:\Program Files\MySQL\MySQL Server 8.0\bin"
mysqld --console --skip-grant-tables --skip-networking
@rem 4. 新開管理員 CMD 窗口
mysql -u root
@rem 進入客戶端後執行重置語句 (同 Linux 版本區分 5.7/8.0)
@rem 5. 關閉啟動窗口 (Ctrl+C),正常啟動服務
net start mysql80
@rem 6. 驗證
mysql -u root -p"NewStrongPass#2024!" -e "SELECT VERSION();"
# 1. 停止容器
docker stop mysql-container
# 2. 啟動臨時容器掛載數據卷,跳過權限
docker run --rm -it \
-v mysql-data:/var/lib/mysql \
-v mysql-conf:/etc/mysql \
mysql:8.0 \
mysqld --skip-grant-tables --skip-networking
# 3. 新終端進入容器 (或 docker exec 另一容器連接)
# 若上述容器暴露端口:mysql -h 127.0.0.1 -u root
# 若未暴露:需另起客戶端容器連接 --network container:temp-mysql
# 4. 重置密碼 (同版本區分)
# 5. 停止臨時容器 (Ctrl+C),啟動正常容器
docker start mysql-container
| 版本 | 密碼列 | 推薦語句 | 備註 |
|---|---|---|---|
| 5.7 | authentication_string | UPDATE mysql.user SET authentication_string=PASSWORD('newpass') WHERE User='root' AND Host='localhost'; FLUSH PRIVILEGES; | PASSWORD() 函數返回哈希值 |
| 8.0 | authentication_string (存儲插件特定哈希) | ALTER USER 'root'@'localhost' IDENTIFIED BY 'newpass'; FLUSH PRIVILEGES; | 不支持 UPDATE 直接改列,需用 ALTER USER。插件默認 caching_sha2_password。 |
skip-networking 僅允許本地 Socket 連接。--skip-grant-tables 期間**任何人可免密 Root 登錄**。validate_password 策略 (長度、大小寫、數字、特殊字符),避免設置後無法登錄。| 報錯 | 原因 | 解決 |
|---|---|---|
ERROR 1290 (HY000): The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement | 8.0 下 --skip-grant-tables 隱含 --skip-networking 且**禁用 FLUSH PRIVILEGES / ALTER USER** 等權限操作 (安全增強) | 啟動後執行 FLUSH PRIVILEGES; **一次**,然後再執行 ALTER USER。或臨時註釋 skip-grant-tables 重啟改密 (需知舊密碼)。 |
ERROR 1820 (HY000): You must reset your password using ALTER USER statement | 密碼過期策略生效 | 使用 ALTER USER 重置即可。 |
Access denied for user 'root'@'localhost' (正常模式下) | 密碼未生效 / Host 不匹配 (localhost vs 127.0.0.1 / %) | 檢查 SELECT User, Host, plugin FROM mysql.user WHERE User='root';,補全 Host 記錄。 |
Root 密碼重置核心是 --skip-grant-tables --skip-networking 臨時啟動。**MySQL 8.0 必須用 ALTER USER**,5.7 用 UPDATE ... PASSWORD()。**生產環境安全第一:網絡隔離、最小化窗口、複雜密碼、全程記錄**。建議將此流程封裝為 Ansible Playbook / Shell 腳本 / Runbook,定期演練。