MySQL ERROR 1045 Access denied排查指南:从报错原理到root密码重置

发布时间:2026/9/15 16:58:27
MySQL ERROR 1045 Access denied排查指南:从报错原理到root密码重置 说实话现在很多新手第一次在服务器或者本机上装好MySQL高高兴兴敲下mysql -u root -p输入密码回车结果屏幕直接甩出一行红字ERROR 1045 (28000): Access denied for user rootlocalhost (using password: NO)那一刻的心情我太懂了——明明刚装好的东西怎么就登录不上去了更懵的是using password: NO到底是什么意思是说我密码没输对吗可密码是安装时候我自己设的呀。我把这些年线上和答疑里遇到的各种1045场景整理了一下尽量讲透不光是照着敲一遍就能过也把为什么会出现和怎么排查一起讲清楚。这个报错在开发环境、测试环境、生产环境都挺常见特别是刚接手别人服务器、本地装完MySQL、以及各种图形化工具突然连不上的时候都属于高发情况。看完这篇你应该能独立解决90%以上的1045问题而不是到处复制粘贴然后祈祷第三条能生效。1. 先看懂这行报错在说什么1.1 不是所有Access denied都一样先拆一下这个报错的信息结构。ERROR 1045是MySQL服务端返回的错误码(28000)是SQLSTATE标准错误码这两个组合在一起就代表了身份认证失败。后面紧跟的for user rootlocalhost说的是哪条账号记录在登录时出了问题root是用户名localhost是客户端来源。很多人的第一反应是我的密码是不是错了但技术上这个报错的触发点分两类using password: NO服务端收到的认证请求里压根没有密码。using password: YES服务端收到了密码但是密码校验没通过。这两种情况的原因和排查方向完全不同。如果光看到Access denied就急着改密码大概率会浪费时间。using password: NO这个场景翻译成人话就是MySQL说你没给密码所以拒绝登录。但你在命令行明明输了密码啊问题往往出在密码根本没被传过去或者你压根没手动指定密码MySQL按空密码来认证了。1.2 几种典型触发时机根据我见到的案例这个报错多数在下面几个时间点出现刚安装完MySQL直接用mysql -u root敲回车没有输入密码的环节。升级或者重新初始化了数据库旧的登录命令还能连上吗不一定。换了连接方式比如之前用Navicat连得好好的某天改用命令行结果报using password: NO。改了配置文件比如socket路径、端口、host匹配规则被调整过。在脚本或者自动化任务里执行mysql命令密码通过命令行传递失败导致服务端收到的认证报文里没有密码字段。现在先说一个最实用的判断逻辑看到using password: NO先别急着重置密码先想想你的客户端到底有没有把密码发出去。真的根据我的经验这个报错里密码错反而是少数没传密码才是大头。2. 排查前置先确定服务状态和连接方式2.1 MySQL服务到底跑没跑这是最基础但最容易跳过的一步。如果MySQL服务根本没起来你执行mysql -u root -p同样会报错但报错信息通常是ERROR 2002 (HY000): Cant connect to local MySQL server through socket。和1045不一样1045说明MySQL服务是活着的而且已经收到了你的认证请求只是在认证环节拒绝了你。不过这不妨碍我们先花十秒钟确认一次服务状态避免后续操作建立在错误假设上# 基于systemd的发行版 systemctl status mysql # 或者 systemctl status mysqld # 老一点的SysV方式 service mysql status不同系统的服务名可能不一样Ubuntu上通常是mysqlCentOS/RHEL上用mysqld居多。如果看到active (running)放心往前走。2.2 你连的是socket还是TCPMySQL客户端连接localhost时默认走的是Unix socket文件并不是TCP/IP。这个细节在排查1045的时候特别重要因为授权表会根据来源Host来匹配账号rootlocalhost只匹配通过socket连接或者解析成localhost的连接。有个很经典的坑明明rootlocalhost存在密码也正确但用mysql -h 127.0.0.1 -u root -p连接却报1045而用mysql -u root -p不带-h却能连上。这就是因为127.0.0.1触发了TCP连接MySQL根据skip_name_resolve的配置决定是否把127.0.0.1反向解析成localhost。如果关闭了反向解析127.0.0.1就会被当成一个独立的Host来源和rootlocalhost对不上。所以确定你的连接方式很重要。执行下面命令可以清晰看到当前连接走的是哪种-- 登录成功后执行 SHOW STATUS LIKE Ssl_cipher; SHOW VARIABLES LIKE socket; SHOW VARIABLES LIKE port;如果看不到这些那至少在你的命令行里注意区分mysql -u root -p和mysql -h 127.0.0.1 -u root -p、mysql -h localhost -u root -p这三种连法在Host匹配上都可能不同。2.3 密码对不对先列个清单自查在动手改配置之前凭经验先问你几个问题基本能缩小90%的范围是刚装完MySQL第一次登录吗之前能连上吗如果能最近改过什么密码是安装时自己设的还是系统生成的报错是using password: NO还是YES用命令行连不上图形工具能连上吗还是都连不上这几个问题的答案能帮你快速锁定场景。我强烈建议你把答案写在纸上然后对照后面的章节去操作而不是看完文章从第一个方案试到最后一个。3. 分场景解决五种最常见的1045 (28000)3.1 刚装完MySQL用mysql -u root直接登录这是新手上路最常踩的坑。事情得从MySQL 5.7开始说起——官方为了安全在安装时会为root账号生成一个临时随机密码不是空密码更不是root或者123456。如果你用的是yum/apt装的MySQL安装完成后root的临时密码写在日志文件里# CentOS/RHEL系 grep temporary password /var/log/mysqld.log # Ubuntu系取决于日志路径 grep temporary password /var/log/mysql/error.log拿到临时密码后用它登录mysql -u root -p然后立即修改密码ALTER USER rootlocalhost IDENTIFIED BY YourStrongPass123!;这里必须提醒一下MySQL 5.7及以上版本默认开了validate_password组件密码要满足一定复杂度不然会报ERROR 1819 (HY000): Your password does not satisfy the current policy requirements。如果实在不想用复杂密码可以临时降低策略SET GLOBAL validate_password.policy LOW;注意MySQL 8.0的变量名是validate_password.policy5.7是validate_password_policy写法不一样别搞混。3.2 明明有密码却提示using password: NO这种情况比上一种更让人抓狂——密码就在脑子里键盘也敲了结果MySQL说我没收到密码。先检查一条最基础的你敲命令的时候-p后面是不是什么都没跟如果有交互式提示密码是在提示符后输入的这是正确姿势mysql -u root -p敲回车后MySQL会显示Enter password:这时候输入的字符不会回显输入完回车就行。很多人会犯一个错误在-p后面直接跟密码但中间不能有空格# 正确写法-p和密码之间不能有空格 mysql -u root -pYourPassword # 错误写法-p后带空格MySQL只看到-p把YourPassword当成了数据库名 mysql -u root -p YourPassword还有一种情况你的~/.my.cnf全局配置文件里写了[client]段里面指定了账号但没指定密码或者密码注释掉了。这种情况下客户端会按照配置文件发送用户信息密码字段为空。# 查看是否有影响连接的配置 cat ~/.my.cnf如果这个文件存在且里面有一行password 但后面是空的MySQL客户端就会认为你要用空密码登录自然就出现using password: NO了。解决办法很简单删除或者修正这个文件里的配置。另外如果你的第三方工具能连上MySQL但命令行连不上那大概率不是MySQL本身的问题而是命令行客户端的配置或参数问题。重点检查客户端版本和配置文件。3.3 忘记root密码用skip-grant-tables模式重置如果确认密码确实忘了或者上述排查都没解决问题终极手段是跳过授权表登录MySQL然后重置密码。这个方案能解决99%的root密码问题但操作时要格外小心。整体思路是让MySQL在启动的时候不加载授权表认证环节直接放行你能以root身份免密进入然后用SQL重置密码。步骤如下第一步停止MySQL服务sudo systemctl stop mysql # 或 sudo systemctl stop mysqld第二步以跳过授权表的方式启动MySQL推荐在配置文件里临时加参数# 以Ubuntu为例编辑mysqld.cnf sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf在[mysqld]段下加一行skip-grant-tables也可以更稳妥地加上skip-networking避免在跳过授权表期间别人通过网络连接进来skip-grant-tables skip-networking保存后启动sudo systemctl start mysql另一种方式是直接用命令行启动sudo mysqld_safe --skip-grant-tables --skip-networking 这种方式在一些环境里可能因为systemd管理等问题跑不起来所以配置文件方式最通用。第三步免密登录mysql -u root不需要密码直接进入MySQL命令行。如果是MySQL 8.0某些版本可能需要mysql -u root -e SELECT 1;只要进去了后面都好办。第四步重置root密码MySQL 5.7和8.0在用户表结构上有差异重置密码的SQL写法也不同。MySQL 5.7之前含5.7早期临时方案常见方式FLUSH PRIVILEGES; UPDATE mysql.user SET authentication_stringPASSWORD(NewPass123) WHERE Userroot; FLUSH PRIVILEGES;MySQL 5.7的authentication_string字段存的就是密码哈希直接UPDATE是可行的但PASSWORD()函数在5.7.6以后被弃用了实际测试仍可用。如果是MySQL 8.0推荐用标准ALTER USERFLUSH PRIVILEGES; ALTER USER rootlocalhost IDENTIFIED BY NewPass123; FLUSH PRIVILEGES;如果ALTER USER报错ERROR 1290 (HY000): The MySQL server is running with the --skip-grant-tables option说明需要先执行FLUSH PRIVILEGES;才能激活权限系统然后再执行ALTER USER。第五步退出恢复配置重启服务EXIT;把配置文件里加的skip-grant-tables和skip-networking注释或删掉然后重启MySQLsudo systemctl restart mysql最后用新密码验证mysql -u root -p注意整个过程最危险的时刻是第四步到第五步之间——跳过授权表期间任何能连到MySQL的人都等于拥有了root权限。所以务必在本地操作配上skip-networking关闭网络监听改完密码立即恢复配置重启。3.4 密码正确但还是1045using password: YES这个方向是很多老手也会卡住的点。如果你已经确定密码没输错、用户也存在、服务也正常报错却是using password: YES那要往认证插件、Host匹配和密码过期状态三个方向查。方向一认证插件不匹配Ubuntu系的MySQLroot账号默认使用auth_socket插件认证。这个插件的逻辑是只要当前系统用户是root就能通过socket连接免密登录MySQL的root账号。但如果你用mysql -u root -p并手动输入密码反而会因为认证插件不接受密码而报Access denied (using password: YES)。遇到这种情况正确登录姿势是sudo mysql -u root进入MySQL后把root的认证方式改为密码认证ALTER USER rootlocalhost IDENTIFIED WITH caching_sha2_password BY YourStrongPass123!;这样就绕过了auth_socket对系统用户的依赖以后用密码也能登录了。顺便说一句8.0默认的缓存认证插件是caching_sha2_password比老旧的mysql_native_password更安全。方向二Host匹配错了MySQL的用户由User和Host两列共同决定。rootlocalhost、root127.0.0.1、root%是三个不同的账号。如果你的客户端来源被MySQL解析成127.0.0.1但授权表里只有rootlocalhost就会拒绝。我经常遇到的一种情况是root%存在但rootlocalhost不存在或密码不同本地用socket连接时匹配不到正确的账号。解决办法就是先登录进去查一下所有root账号SELECT User, Host, plugin FROM mysql.user WHERE Userroot;如果确认需要的Host组合不存在创建或者修改CREATE USER root127.0.0.1 IDENTIFIED BY YourPass; -- 或者 ALTER USER root127.0.0.1 IDENTIFIED BY YourPass;方向三密码过期状态MySQL 5.7.6及以上给root账号默认设置了密码过期策略。密码过期后连接能建立但你执行任何SQL都会报ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.有些场景下这个状态甚至会在图形连接工具上显示为Access denied。处理方式是把密码手动刷新并设置过期策略ALTER USER rootlocalhost IDENTIFIED BY YourStrongPass123! PASSWORD EXPIRE NEVER;3.5 权限表损坏或版本升级后的兼容性问题这种情况相对小众但确实存在。比如MySQL版本跨大版本升级后mysql系统库的表结构没有完全更新导致认证时读取权限信息出错。MySQL 5.7时代可以用mysql_upgrade修复mysql_upgrade -u root -pMySQL 8.0里mysql_upgrade已经整合进了服务启动流程MySQL 8.0.16之后的版本每次启动都会检查系统表版本。如果升级后出现奇怪的认证问题可以考虑先启动--skip-grant-tables进去直接运行CHECK TABLE mysql.user;如果返回损坏状态再用修复工具处理。不过说真的大多数1045问题不会走到这一步这个方向建议放在最后排查。4. 实际问题排查技巧与避坑经验4.1 常见问题速查表我把日常最常被问到的问题整理成一个表格大家可以对照自己的报错快速定位症状可能原因解决方向using password: NO刚装完MySQLroot默认有临时密码查日志里的临时密码登录后改密码using password: NO命令行里明明敲了密码-p和密码之间多空格用交互式方式输入密码using password: NO配置文件有[client]段密码为空或缺失修正~/.my.cnf或命令行显式传参using password: YES密码确定正确auth_socket插件或Host不匹配sudo mysql进入后改认证插件using password: YES之前能连今天不行密码过期重置密码并设置过期策略工具能连命令行连不上客户端配置或Host匹配差异检查~/.my.cnf、socket路径、-h参数skip-grant-tables模式能进但ALTER USER报错权限系统未激活先执行FLUSH PRIVILEGES;8.0下PASSWORD()函数报错函数被移除使用ALTER USER写法4.2 几条压箱底的实操心得第一个心得改密码之前永远先备份。不管是改授权表还是配置文件先把/etc/my.cnf、/etc/mysql/目录下的配置文件复制一份再说。别嫌多此一举我见过太多人改完配置发现MySQL起不来手忙脚乱往回倒腾的。第二个心得生产环境尽量别用skip-grant-tables。如果非用不可一定要加skip-networking确保只有本机能连。改完密码后第一时间去掉这个参数重启恢复权限校验。并且操作完要去看一下MySQL的error log确认没有异常告警。第三个心得尽量避免长期使用root跑业务。创建一个个独立账号权限最小的账号是个好习惯CREATE USER app_userlocalhost IDENTIFIED BY AppPass123!; GRANT ALL PRIVILEGES ON myapp.* TO app_userlocalhost; FLUSH PRIVILEGES;这样即使连接串被泄露影响范围也有限。而且很多1045问题都是root被锁、权限被改导致的业务账号独立后root出问题不至于影响线上业务。第四个心得命令行连接工具选对客户端版本。如果你用Navicat连MySQL 8.0没问题但IDEA连不上并报1045很可能是JDBC驱动版本太老不认识caching_sha2_password插件。解决方法是升级JDBC驱动到8.0以上或者在URL里加上allowPublicKeyRetrievaltrueuseSSLfalse。这种问题不是MySQL配置错误纯粹是客户端兼容性。第五个心得养成看日志的习惯。MySQL的error log里有时候会记录详细的认证失败原因比如Access denied for user rootlocalhost (using password: NO)旁边可能跟着一条警告提示某个插件拒绝了请求。日志路径一般在/var/log/mysql/error.log或/var/log/mysqld.log排查问题比瞎试命令高效得多。4.3 一个完整的实战排查示例最后分享一个我最近帮朋友处理的案例你可以完整走一遍这个思路。朋友说Navicat连不上本地MySQL 8.0报错1045 (using password: YES)。我的排查流程是先问密码是刚设的还是以前的——他说是刚装的MySQL密码是安装的时候设的。让他在命令行试一下mysql -u root -p结果能登录说明MySQL服务和root账号本身没问题。问题定位到Navicat侧。看版本发现是老版本不支持caching_sha2_password插件。解决办法有两个升级Navicat或者把root的认证插件改成mysql_native_password后者的SQL是ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY YourPass;实测改完插件后Navicat秒连成功。但如果是在生产环境我更推荐去升级客户端工具而不是降级认证插件毕竟mysql_native_password在8.0里属于废弃插件出于安全考虑不宜长期使用。根据我个人这几年实际维护数据库的经验遇到1045先别慌按照看NO还是YES、确认密码来源、检查认证插件、核对Host列表、最后才考虑重置密码这个顺序走一遍绝大多数情况五分钟内能解决。真正无解的其实是那些配置文件和授权表同时出问题的复杂环境那种情况下先恢复配置备份再用跳过授权表方式修复密码一步步来基本都不会翻车。