资讯动态

MySQL 1045 Access Denied终极排查:密码重置与认证插件全攻略

发布时间:2026/9/17 10:57:24 来源:尧图企业网站定制
1. 先搞懂 1045 到底在说什么遇到1045 - Access denied for user rootlocalhost (using password: YES)大多数人的第一反应是“我密码是不是记错了”。这个判断方向没错但只覆盖了一部分原因。我接触过的 1045 报错场景里至少有一半以上不是密码本身的问题而是密码校验方式、host 匹配规则、权限表状态或者客户端插件不兼容导致的。先把这条报错拆开看。1045是 MySQL 的特定错误码对应Access denied意思是“访问被拒绝”。后面的rootlocalhost指的是你尝试登录的账号是root来源主机是localhost。末尾的(using password: YES)表示客户端确实提交了密码并不是空密码登录。很多人会被最后这段误导以为“我明明用了密码为什么还说密码不行”其实 MySQL 只是告诉你它收到了密码不代表密码正确。MySQL 的账号体系是“用户名 来源主机”双维度定义的。也就是说rootlocalhost和root127.0.0.1在 MySQL 看来可能是两个不同账号root%又是另一个账号。很多人只记住了用户名忘了 host 这层概念。比如你尝试用root从远程连接目标库里的 root 账号只绑定了localhost那么无论密码对不对都可能报 1045而且提示里的 host 会是你的客户端 IP 而不是localhost。从底层逻辑来看MySQL 校验登录分三步先根据用户名和来源 IP 匹配mysql.user表里的记录找不到对应记录就直接拒绝找到记录后再验证密码密码不对就报 1045密码通过后还要看账号是否被锁定、是否过期这些状态异常也会导致登录被拒。所以 1045 本质上是一个“登录认证失败”的兜底错误具体卡在哪一步需要结合报错信息和现场环境去判断。这篇文章适合谁看刚装完 MySQL 连不上、改过密码后突然进不去、用 Navicat 或 IDEA 等客户端连接时报 1045、服务器重启后 root 无法登录、数据库跑着跑着 root 账号莫名其妙失效的这些人。下面我把排查思路、解决步骤和踩坑经验一次性说清楚。2. 动手排查前先做这几件事2.1 快速确认问题范围修 1045 之前务必先确认几个信息否则可能白忙活半天。第一这个报错是刚安装完就出现还是原本能连、某次操作之后才出现两者原因方向完全不同。第二你用的是命令行还是 Navicat、IDEA 这类图形工具不同连接方式走的认证路径有差异。第三MySQL 版本是多少5.x 和 8.x 的密码存储机制、默认认证插件都不一样处理方式差别很大。我建议按下面这个清单逐一核对端口能不能通在服务器上用mysql -uroot -p本地登录试试如果本地也报 1045说明问题在 MySQL 服务端如果本地能登录、远程连不上问题大概率在账号 host 匹配或 bind-address 配置上。服务是否正常确认 MySQL 进程在跑ps -ef | grep mysql、systemctl status mysql或 Windows 服务管理器都能看。密码是否有大小写或隐藏字符手动输入密码时容易出错建议用复制粘贴或者先在别处输入到文本文件里确认无误再粘贴。是否近期动过权限表比如执行过UPDATE mysql.user SET ...或GRANT语句如果改坏了会影响整个认证流程。2.2 临时绕过认证的准备工作一旦确认密码确实无法通过需要进入 MySQL 做内部修复。这时最常用的办法是跳过权限认证启动 MySQL也就是在配置文件里加一行skip-grant-tables。这个参数的意思很直白启动时不再加载权限表任何用户都能免密进入服务端。注意这是临时应急手段不是日常开机配置修复完成后必须关闭它再重启。在执行跳权限操作前建议先备份配置文件和数据目录里的mysql库尤其是mysql.user表。虽然改密码一般不动表结构但万一执行错 SQL备份能救你一命。另外要确认 MySQL 安装位置和数据目录。Windows 上一般是C:\Program Files\MySQL\MySQL Server 8.0\Linux 上则要看发行版Ubuntu 和 Debian 系通常是/etc/mysql/CentOS 和 RHEL 系通常是/etc/my.cnf。配置文件路径不对改了半天等于没改。3. 核心解法通过 skip-grant-tables 重置 root 密码3.1 Windows 下的完整操作步骤以 Windows 上最常见的 MySQL 8.0 为例。先打开服务管理器找到 MySQL 服务并停止它。然后找到配置文件my.ini一般在 MySQL 安装目录下。用管理员权限编辑在[mysqld]段下面加一行[mysqld] skip-grant-tables保存后启动 MySQL 服务。接着打开命令行不需要密码直接执行mysql -uroot看到mysql提示符后先不要急着改密码先执行FLUSH PRIVILEGES;这一步很关键。跳过权限认证后MySQL 虽然允许你进入但内存里的权限模块并没有加载。如果不执行FLUSH PRIVILEGES直接执行ALTER USER或SET PASSWORD在一些版本里会报错。先刷新让权限系统从磁盘加载完整数据后面才能正常修改。然后重置密码。MySQL 5.7 及以下版本用UPDATE mysql.user SET authentication_stringPASSWORD(新密码) WHERE Userroot AND Hostlocalhost;MySQL 8.0 不再支持PASSWORD()函数必须用ALTER USER语法ALTER USER rootlocalhost IDENTIFIED BY 新密码;执行成功后退出mysql环境回到命令行。先把配置文件里skip-grant-tables那行删掉或注释掉再重启 MySQL 服务。这次用新密码登录应该就通了。3.2 Linux 下的操作差异Linux 下原理一样但要注意几个细节。以 Ubuntu 20.04 MySQL 8.0 为例配置文件路径是/etc/mysql/mysql.conf.d/mysqld.cnf主配置文件/etc/mysql/my.cnf里会!includedir引入这个目录。如果两个文件里都有[mysqld]段修改哪个都行重要的是确保被加载。编辑文件加上skip-grant-tables后重启 MySQL 服务sudo systemctl restart mysql然后免密进入mysql -uroot如果你打算用UPDATE mysql.user改密码注意 MySQL 5.7 之后的authentication_string存的是哈希值不是明文不能直接SET authentication_string 新密码。正确做法要么用ALTER USER要么在 5.7 用PASSWORD(新密码)函数生成哈希再更新。8.0 已经移除了PASSWORD()所以推荐统一用ALTER USER。改完密码后删除配置文件里的skip-grant-tables重启服务用密码登录验证。3.3 免密登录后必须做的安全收尾跳过权限认证期间MySQL 相当于门户大开任何人只要知道端口就能免密连接。有几种情况要注意如果bind-address是0.0.0.0意味着所有网卡都在监听局域网内其他机器也能连接。如果skip-grant-tables生效期间执行了FLUSH PRIVILEGESMySQL 会重新加载权限表不清除免密模式但权限验证会恢复部分逻辑。修复完成后一定要回头把配置文件还原并重启服务否则你等于把自己的数据库裸奔在外。我个人的习惯是修复过程中全程只监听本地也就是进入系统后只在命令行操作不通过远程工具连修复完成重启后立刻用mysql -uroot -p验证并且检查SHOW VARIABLES LIKE skip_grant_tables的输出是OFF确认免密状态已关闭。4. 不重启 MySQL靠权限修复操作解决问题4.1 重启不是唯一出路用保留的合法账号登录如果你有另一个有权限的 MySQL 账号比如admin或者root的一个能用的 host 条目那就不用走skip-grant-tables这条险路。直接正常登录然后执行权限修复。典型场景是这样的服务器上rootlocalhost密码忘记但你还保留着root127.0.0.1的密码权限或者自己建的admin账号。这时用mysql -uroot -h127.0.0.1 -p登录然后执行ALTER USER rootlocalhost IDENTIFIED BY 新密码;这里要注意一点不同 host 的 root 账号密码是独立的。如果你只改了rootlocalhost远程用root%连接还是旧密码同样会报 1045。所以排查时要先确认你到底是哪种方式登录。SELECT User, Host, plugin, account_locked FROM mysql.user;这条 SQL 能看到当前 MySQL 里所有账号的绑定关系。plugin列显示的是认证插件account_locked显示是否被锁定。MySQL 8.0 默认插件是caching_sha2_password老客户端如果只支持mysql_native_password连上去也可能报 1045这个问题后面单独说。4.2 密码复杂度引起的连带问题MySQL 8.0 默认开了密码校验插件validate_password如果你设置的密码太简单ALTER USER会直接报错。比如123456这种会提示Invalid password让你以为 SQL 写错了其实是密码强度不够。解决办法有两种。要么设置一个复杂度够的密码比如包含大小写字母、数字和特殊符号且长度超过 8 位要么临时调整密码策略SET GLOBAL validate_password.policy LOW; SET GLOBAL validate_password.length 6;注意 8.0 的变量名是从validate_password.policy开始老版本是validate_password_policy不要搞混。密码改完后建议把策略改回来毕竟安全底线不能丢。4.3 注意密码插件不兼容导致的 1045这是一个很隐蔽的问题。你用命令行登录 MySQL 8.0 正常但用 Navicat、IDEA 或老版本 JDBC 驱动连接时却报 1045而且提示还明确写着using password: YES。这种情况十有八九是密码插件不兼容。MySQL 8.0 默认使用caching_sha2_password加密认证而一些老客户端默认只支持mysql_native_password。虽然客户端会尝试协商但如果协议不匹配服务端直接拒绝认证表现就是 1045。解决办法是把这个账号的插件改成旧版ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 新密码;改完后客户端即使版本旧也能正常连接。不过要注意mysql_native_password在 MySQL 8.4 被标记为废弃长期方案是更新客户端驱动而不是一直用旧插件。5. 实操案例Navicat 连接 MySQL 报 1045 的完整排查举一个我实际处理过的案例。一个朋友装完 MySQL 8.0命令行用mysql -uroot -p输入安装时设置的密码能正常登录但 Navicat 连同一台机器填同样的 3306 端口、用户名和密码却报 1045Access denied for user rootlocalhost (using password: YES)。这种“命令行能进、图形工具进不去”的情况很多人会怀疑软件问题但其实核心在认证方式。第一步我用命令行登录后执行SELECT user, host, plugin FROM mysql.user WHERE userroot;返回结果里plugin是caching_sha2_password这就基本确定问题了。Navicat 版本较老不支持这个插件所以在认证协商阶段就被拒绝。处理办法就是在 MySQL 里把 root 的插件临时切换成mysql_native_password并重置一个密码ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY root123456; FLUSH PRIVILEGES;再试 Navicat 连接直接成功。如果你不想临时改密码也可以在 MySQL 里新建一个专用账号给工具连CREATE USER navicat_user% IDENTIFIED WITH mysql_native_password BY navicat_pass; GRANT ALL PRIVILEGES ON *.* TO navicat_user%; FLUSH PRIVILEGES;我比较推荐后一种做法因为 root 是超级账号日常工具连接用最小权限的专用账号更安全还能避免误删、误改整个库的风险。从这个案例还能引出另一个容易被忽略的点Navicat 最新版本其实已经支持caching_sha2_password如果你用的老版本先别急着改 MySQL 插件试着升级一下 Navicat 或者换用 MySQL Workbench。非要改插件的话记得评估以后程序连接是否有兼容性问题改完以后最好测试所有业务连接。还有一个细节Navicat 新建连接的“高级”选项卡里如果勾选了“使用压缩协议”某些版本会有协议兼容性问题。排查时可以先取消这个选项再试一次。6. 常见问题速查表与避坑清单下面这些是我这些年经常遇到的 1045 场景整理成表格方便快速对照。现象可能原因解决办法命令行登录报 1045密码错误root 密码错误或账号 host 不匹配用 skip-grant-tables 重置密码Navicat 连接报 1045命令行正常客户端密码插件不兼容切换 mysql_native_password 或升级客户端localhost 能连127.0.0.1 连不上账号只绑定了 localhost创建 root127.0.0.1 账号或修改 host远程 IP 连接报 1045root 没开启远程访问权限创建 root% 或授权具体 IP服务器重启后 root 无法登录权限表损坏或配置被改检查 skip-grant-tables、修复 mysql 库改密码时报错 Invalid password密码复杂度策略限制调整 validate_password 策略MySQL 8.0 改密码时 function PASSWORD 报错8.0 移除了 PASSWORD() 函数用 ALTER USER 语法host 连接拒绝报 Host is not allowed账号绑定的 host 范围太小授权时使用%或具体 IP再补几条容易踩的坑。第一个坑skip-grant-tables加完后mysql -uroot还是进不去。常见原因是配置文件加载顺序问题你改的文件根本没被 MySQL 读取。用mysqld --verbose --help | grep my.cnf可以查看当前实际读取的配置文件顺序确保你改的文件在列表里。或者用SHOW VARIABLES LIKE basedir查看安装目录再去对应位置找配置。第二个坑执行ALTER USER后不生效重启后又回到旧密码。这是因为你用了skip-grant-tables启动后部分 MySQL 版本对权限表的修改写入有延迟或缓冲。解决方法是改完密码后立刻执行FLUSH PRIVILEGES然后干净地关闭服务不要直接kill -9杀进程。第三个坑Windows 下改了my.ini但 MySQL 服务启动失败。很可能是换行符或者编码问题保存时记得选 UTF-8 编码不要带 BOM。另外my.ini里有中文注释时某些版本会因解析问题导致服务异常临时处理方法就是先去掉中文注释再重启。第四个坑账号account_locked字段被置为Y。如果你不小心执行了ALTER USER rootlocalhost ACCOUNT LOCK即使密码正确也会报 1045。排查时可以用SELECT user, host, account_locked FROM mysql.user看看状态如果是Y用ALTER USER rootlocalhost ACCOUNT UNLOCK解锁。7. 我的几个实操心得修 1045 这种问题最忌讳的就是一上来就暴力重置密码。我在实际排查中养成了一套固定习惯供你参考。第一先判断是单点问题还是全局问题。如果只有某个客户端连接报 1045其他工具正常优先怀疑这个客户端的认证兼容性而不是去重置密码。如果所有客户端包括命令行都报 1045才是密码或账号问题。第二做任何修改前先导出mysql库。执行mysqldump -uroot -p mysql mysql_backup.sql几百 KB 的文件避免改错以后无法回滚。第三明确 host 的含义。MySQL 的 host 不仅支持localhost、127.0.0.1还支持%、具体 IP、网段掩码甚至主机名。授权时尽量缩小范围不要图省事直接给%。root%这种账号虽然方便但一旦密码泄漏影响面是整个库。日常只给业务账号开远程权限root 保持 localhost 就好。第四MySQL 8.0 和 5.7 的差异要刻在脑子里。5.7 用mysql.user表里的authentication_string存储哈希8.0 同样是这个字段但密码生成算法、默认插件都变了。网上很多教程还在用老语法直接抄会报错。多看官方文档里ALTER USER的用法才是稳妥的方式。第五skip-grant-tables修完后必须确认关闭。我见过有人修完密码后忘了删配置数据库一直处于免密状态跑了半年最后被人连上来删了库。这种事故不难避免关键是养成检查习惯重启后用SHOW VARIABLES LIKE skip_grant_tables;看一眼输出是OFF才放心。最后说一个扩展建议。如果你的项目里有多套 MySQL 环境建议单独维护一个账号密码管理文档记录每套环境的版本、root 账号、host 绑定关系、认证插件和最后修改时间。1045 这种问题很多时候就是因为版本差异、账号职责不清导致误改误删。把环境信息梳理清楚排查时间能缩短一半以上。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价