Ubuntu服务器上MySQL 8.0+修改root密码后无法登录,是典型的身份验证插件不兼容问题。MySQL 8.0默认使用`caching_sha2_password`插件,而部分客户端(如旧版mysql-client、某些GUI工具或脚本)仅支持`mysql_native_password`。若执行`ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'xxx';`后未同步更新插件或未刷新权限,会导致连接被拒绝(错误1698:Access denied for root@localhost)。此外,跳过密码验证启动时未正确执行`FLUSH PRIVILEGES`、`auth_socket`插件残留、或`/etc/mysql/mysql.conf.d/mysqld.cnf`中误配`skip-grant-tables`未清理,也会引发登录失败。排查需优先检查`SELECT user, host, plugin FROM mysql.user WHERE user='root';`,确认插件类型与密码是否生效,并验证配置文件与systemd服务状态。切忌直接删除root用户或盲目重装——精准修复插件与权限即可恢复访问。
1条回答 默认 最新
诗语情柔 2026-02-27 19:21关注```html一、现象定位:从错误码切入,识别身份验证层故障
当执行
mysql -u root -p后报错ERROR 1698 (28000): Access denied for user 'root'@'localhost',本质是认证链路在插件层中断。MySQL 8.0+ 默认启用caching_sha2_password(SHA-256 + 缓存优化),而 Ubuntu 20.04/22.04 自带的mysql-client(v8.0.33 以前)或 DBeaver、HeidiSQL 等旧版 GUI 工具默认不支持该插件的完整握手流程——尤其缺失 RSA 公钥交换或未启用--default-auth=mysql_native_password参数。二、核心诊断:三维度交叉验证用户状态
需在安全模式下启动 MySQL 并执行以下诊断语句:
SELECT user, host, plugin, authentication_string, account_locked FROM mysql.user WHERE user = 'root';重点关注三列:
plugin(应为mysql_native_password或兼容值)、authentication_string(非空且含哈希值)、account_locked(应为N)。若 plugin 显示auth_socket,说明仍残留 Ubuntu 包安装时的 socket 认证逻辑(常见于sudo apt install mysql-server默认配置)。三、配置溯源:检查 mysqld.cnf 与 systemd 启动上下文
配置项 风险位置 安全建议 skip-grant-tables/etc/mysql/mysql.conf.d/mysqld.cnf仅临时调试使用;必须注释并 sudo systemctl restart mysql,否则权限系统完全失效default_authentication_plugin同一文件中 [mysqld] 段 设为 mysql_native_password可全局降级兼容性(生产环境慎用)四、修复路径:分场景精准重置认证机制
- 场景A(已可登录但插件不兼容):执行
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YourStrongPass123!'; FLUSH PRIVILEGES; - 场景B(完全无法登录):先以
sudo mysqld --skip-grant-tables --skip-networking &启动,再连入执行上述 ALTER + FLUSH,最后sudo killall mysqld并正常启动服务 - 场景C(auth_socket 残留):执行
UPDATE mysql.user SET plugin='mysql_native_password', authentication_string=PASSWORD('xxx') WHERE user='root' AND host='localhost';(注意:PASSWORD() 在 8.0.26+ 已弃用,应改用SHA2('xxx',256))
五、客户端适配:跨工具兼容性加固
除服务端修复外,客户端需同步调整:
- 命令行:显式指定插件
mysql -u root -p --default-auth=mysql_native_password - DBeaver:连接设置 → Driver properties →
allowPublicKeyRetrieval=true&useSSL=false(配合 caching_sha2_password) - Python pymysql:升级至 v1.1.0+,并添加参数
auth_plugin='mysql_native_password'
六、验证闭环:自动化检测脚本(Bash)
#!/bin/bash # 验证 root 认证状态 echo "=== MySQL Root 用户认证状态 ===" sudo mysql -Nse "SELECT CONCAT(user, '@', host, ' → ', plugin) FROM mysql.user WHERE user='root'" 2>/dev/null || echo "ERROR: MySQL 未运行或权限不足" echo -e "\n=== 连接性测试 ===" if mysql -u root -p'YourStrongPass123!' -e "SELECT VERSION();" &>/dev/null; then echo "✅ 成功连接 MySQL 8.0+" else echo "❌ 连接失败,请检查插件与密码" fi七、深度原理:caching_sha2_password 握手流程图
graph LR A[Client connects] --> B{Plugin supported?} B -->|Yes| C[Send SHA256 password hash] B -->|No| D[Request public key] D --> E[Server sends RSA public key] E --> F[Client encrypts password with RSA] F --> G[Server decrypts and validates] C --> H[Authentication success] G --> H H --> I[Session established]八、生产规避策略:部署阶段最佳实践
在初始化 MySQL 实例时即规避问题:
- 使用
mysqld --initialize-insecure后立即执行插件强制设定 - Ansible Playbook 中统一注入:
mysql_user: name=root host=localhost plugin=mysql_native_password password={{ db_root_pass }} - 容器化部署(Docker)时,在
my.cnf中预设default_authentication_plugin=mysql_native_password
九、进阶排查:systemd 服务状态与 socket 文件冲突
Ubuntu 的
mysql.service可能因ProtectHome=true或PrivateTmp=true导致 socket 路径不可见。执行:sudo systemctl show mysql | grep -E "(Protect|Private)" sudo ls -l /var/run/mysqld/mysqld.sock # 若 socket 不存在,检查 /etc/mysql/mysql.conf.d/mysqld.cnf 中 socket=/var/run/mysqld/mysqld.sock 是否被覆盖十、终极保障:备份与回滚机制设计
修复前务必执行:
sudo mysqldump -u root -p --all-databases --routines --events > full_backup.sqlsudo cp /var/lib/mysql/mysql/user.MYD /tmp/user_backup.MYD(MyISAM 表物理备份)- 记录当前
SELECT @@version_compile_os, @@version_comment;用于版本兼容性审计
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报- 场景A(已可登录但插件不兼容):执行