
升级这事谁升谁知道。我前几天把一台测试环境的MySQL从5.7.43升到8.0.44本来想着就是常规操作结果登录那一步就给我脸色看了——ERROR 1045 (28000): Access denied for user rootlocalhost紧接着又是ERROR 2026 (HY000): TLS/SSL connection error一串一串的报错直接把我整懵了。当时第一反应是“密码不是没改过吗”但排查下去才发现8.0.44这个版本在认证插件、SSL配置和权限校验上都有不少新变化很多在5.7里用得顺手的老方案到这儿全不灵了。这篇文章我就把这次升级后遇到的登录报错、根因定位、解决方案和几个容易忽略的坑完整记录下来给准备升8.0.x、尤其是直接升8.0.44的朋友做个参照。1. 8.0.44升级后登录报错的典型症状与根因定位1.1 三种最常见的登录报错表现在我实际处理过的案例里升级到8.0.44后登录报错基本逃不出这三种形态而且往往还是交叉出现的。第一种是权限类的ERROR 1045 (28000)提示“Access denied for user”这个最常见升级前好好的账号升级完就登不进去了。第二种是连接层的ERROR 2002 (HY000)提示“Cant connect to local MySQL server through socket”这个往往不是权限问题是服务没起来、socket路径对不上或者数据目录的元数据没升级完导致启动失败。第三种是SSL层面的ERROR 2026 (HY000)提示“TLS/SSL connection error”这个在8.0.44里尤其值得注意因为新版对TLS的默认策略比老版本严格得多。还有个容易被忽略的启动期报错就是日志里出现[ERROR] [MY-014060] [Server] Invalid MySQL server upgrade。我最初看到这个报错时也是一头雾水后来才明白这是mysqld在启动时发现数据字典里的版本号和应用二进制版本不一致——换句话说你如果直接拿8.0.44的二进制文件去启动老版本的数据目录、却没走正常的升级流程就会卡在这一步表现在外头就是“服务起来了但登录连不上”或者“干脆起不来”。1.2 报错背后的关键机制从5.7到8.0.44发生了什么要搞懂为什么登录会大面积报错得先清楚5.7和8.0这两代之间的几个关键差异。最核心的一条是默认认证插件变了5.7默认用mysql_native_password而8.0.44默认用caching_sha2_password。这个插件用SHA-256算法做加盐口令校验安全性高了一截但很多老版本客户端、老驱动根本不认。你拿Navicat老版本、PHP 5.x环境、或者没更新过JDBC驱动连上去结果就是在握手阶段直接返回Authentication plugin caching_sha2_password cannot be loaded或干脆是1045。表现形式是密码正确也登录失败。第二个关键点是权限表结构变化。8.0把用户信息、权限信息全部移交给了数据字典mysql.user表结构也和5.7完全不同。如果你没有通过mysqld --initialize重新初始化、也没有做升级步骤用户数据在新旧结构之间就容易出现错位登录校验时找不到正确的认证插件信息自然就连不上。这也是为什么升级流程和全新安装的流程不能混着来。第三个点是SSL/TLS默认策略收紧。8.0.44里客户端连接时如果双方没有明确的TLS协商某些版本组合下会出现TLS证书校验失败报SSL connection error或Server public key not available。这里涉及一个容易混淆的点有几个错误其实不是SSL本身坏了而是客户端想用老式RSA公钥交换来传输密码但服务端没开放这个通道于是被误报成SSL问题。第四个点是安装方式引发的差异。热词里很多人搜“rpm安装mysql”“docker安装mysql”“linux mysql 8.0.44 下载”这三种方式在升级时踩的坑完全不同。RPM安装有系统级systemd服务管理数据目录权限和SELinux都可能拦一道Docker镜像里的配置路径、默认参数和物理机不一样容器内socket路径和数据卷映射容易搞错源码或通用二进制包安装则纯粹靠自己处理目录结构和初始化。后面我按场景拆方案时会把这些差异点带进去。2. 首次登录错误临时密码、Socket与root账户的坑2.1 升级后必须处理的临时密码问题先讲一个特别容易犯的低级错误。很多人从5.7升级后习惯性用自己以前设置过的密码直接登录结果发现怎么都登不进去。原因在于如果用官方推荐的方式——比如把8.0.44的数据目录指向了原有数据目录mysqld在启动时检测到数据字典版本不匹配会进入升级模式这时候root账号的认证信息可能被重置。更常见的是全新安装8.0.44之后第一次登录必须用初始化时生成的临时密码。这个临时密码是随机字符串写在错误日志文件里。Linux下路径一般是/var/log/mysqld.log如果用RPM装也可能是/var/log/mysql/mysql.log。我的习惯是grep -i temporary password /var/log/mysqld.log拿到临时密码后登录命令要用-p紧跟密码或回车后交互式输入别在命令行里明文带密码免得键盘记录。登录成功后直接执行ALTER USER rootlocalhost IDENTIFIED BY 你的新密码;注意这条语句有个隐藏条件8.0.44默认装了validate_password组件密码强度不够会被拒绝通常要求至少8位、包含大小写字母、数字和特殊字符。你如果图省事设一个弱密码会看到类似ERROR 1819 (HY000): Your password does not satisfy the current policy requirements的提示。处理办法要么按要求设强密码要么临时卸载组件但生产环境建议保留强度校验。如果你确认密码没记错、也改过了但还是1045那就不是临时密码的问题直接跳到下一节看认证插件。2.2 Socket连接失败的排查要点ERROR 2002这类socket连接失败在升级场景里往往比权限错误更隐蔽。它会提示Cant connect to local MySQL server through socket /var/run/mysqld/mysqld.sock这时候很多人第一反应是数据库没启动但有时候服务其实起来了就是socket路径对不上。升级后出现这个问题优先级最高的是先检查mysqld进程状态systemctl status mysqld # 或者 ps -ef | grep mysqld如果进程在再用mysqladmin status -p测试连接。服务不在就看错误日志重点确认是不是我前面提到的[ERROR] [MY-014060] [Server] Invalid MySQL server upgrade。这个报错一旦出现说明bin目录和data目录版本错配了进程会反复重启socket自然起不来。如果进程正常但socket路径不对一般是参数文件my.cnf里的socket配置和客户端连接时指定的路径不一致。RPM安装的默认socket是/var/lib/mysql/mysql.sock而Ubuntu等发行版可能是/var/run/mysqld/mysqld.sockDocker容器里又可能是/tmp/mysql.sock。快速验证方式mysql -u root -p --socket/var/lib/mysql/mysql.sock能连上就说明路径问题后续把/etc/my.cnf或客户端配置里的路径改统一即可。这类问题看着低级但升级场景里还真不少见因为不同安装方式带来的默认值差异太容易混淆了。3. 认证插件不匹配导致的1045与兼容方案3.1 caching_sha2_password与老客户端的矛盾来聊聊最普遍的1045问题。前面说了根子在默认认证插件换了而且8.0.44的登录流程对插件校验更严格。你以为密码输对了但服务端在验证密码之前先要看客户端在握手阶段是否支持当前账号的认证插件插件不认密码对也白搭。怎么判断自己是不是掉进这个坑里最简单的办法是找一台能登录的环境查看账号当前的插件SELECT user, host, plugin FROM mysql.user WHERE user root\G输出里如果plugin列是caching_sha2_password而你的客户端版本很老那问题基本就锁定了。让人头疼的是很多老的数据库管理工具或者框架代码底层库用的是多年没更新的libmysqlclient、mysql-connector它们根本不认识这个新插件。另一个隐藏点在于即使客户端支持caching_sha2_password在非SSL连接下首次认证还需要通过RSA公钥交换来传递密码。MySQL 8.0.44默认会生成公钥文件但如果你在参数文件里显式关了caching_sha2_password_auto_generate_rsa_keys又没配好公钥客户端就会报你意想不到的错。3.2 三种兼容方案与选择建议针对插件不匹配的问题我整理出三条可行路线按推荐优先级排。路线一升级客户端支持新插件。MySQL官方对8.0的驱动支持已经非常成熟不管是连接器/C、连接器/J还是Python的mysqlclient新版本都原生支持caching_sha2_password。这也是一直推荐的长期方案。比如Java项目里把JDBC驱动从5.1.x升级到8.0.x版本通常在pom.xml或build.gradle里更新一下依赖就解决了。开发框架是老款PHP的比如PHP 5.x那就得认真考虑框架改造了这个后面单独说。路线二把账号的认证插件改回mysql_native_password。这个方案胜在立竿见影什么老客户端都能立刻连上。我现场处理时一般这么操作ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码; FLUSH PRIVILEGES;改完之后再执行查询确认一下插件已经切换。但我不建议把这个当作永久方案因为mysql_native_password在MySQL 8.0官方路线里已经标记为弃用8.0.44虽然还支持但未来版本大概率移除到时候还得再改造一轮。如果手里有大量存量旧客户端、短期改不动可以先这样过渡。路线三全局压低默认认证插件兼容性。在/etc/my.cnf的[mysqld]段增加配置[mysqld] default-authentication-pluginmysql_native_password注意一个细节这个参数在8.0.44里官方已经标记为过期只是在部分低版本里还生效。8.0.44实测在某些安装包版本中该参数已不再起作用新创建的用户依旧默认caching_sha2_password。所以如果想靠这个全局参数兜底一定要确认你的版本是否支持不要想当然。我从踩坑经历出发建议以“新建账号显式指定插件”为主全局配置为辅CREATE USER app_user% IDENTIFIED WITH mysql_native_password BY 复杂密码; GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO app_user%;3.3 老PHP环境等特殊场景的处理有一个热搜词我得多说一嘴“php mysql 连接失败”。很多老项目的PHP环境还停留在PHP 5.x自带的mysql扩展和mysqli扩展对caching_sha2_password支持非常差升级数据库后直接白屏或报“Connection failed: Password mismatch”。这种场景下再怎么改账号插件都白搭因为老扩展连握手协议都已经过时了关键是PHP版本本身已经不适合对接MySQL 8.0。这时候就要权衡了到底是改数据库兼容老PHP还是升级PHP走新驱动我的处理经验是如果项目代码还能维护优先升级PHP到7.x/8.x配上官方新版mysqli或PDO驱动彻底解决兼容问题如果代码实在动不了短期内只能给目标账号设置mysql_native_password但别忘了这只是拖延战术该升级还得升。4. SSL连接报错与TLS配置问题4.1 8.0.44的SSL默认策略到底改了什么如果说认证插件是大家熟悉的老坑那SSL问题就是8.0.44给运维的一次“新惊喜”。升级后登录时如果碰到ERROR 2026 (HY000): TLS/SSL connection error大概率不是因为证书过期而是因为默认的TLS版本和密码套件策略变了。MySQL 8.0系列从8.0.30左右开始官方逐步收紧了对老TLS协议的支持。到8.0.44这代很多低版本客户端如果只支持TLSv1.0或TLSv1.1服务端在握手阶段就不会跟它建立SSL连接但客户端还不停地往SSL走于是报错。此外如果服务端配置了require_secure_transportON在非SSL连接下直接就会被拒绝报ERROR 1045或ERROR 3159。我在排查时发现一个特别容易误导人的现象报错文本提到“SSL”但实际是密码传输通道问题。首次连接诸如caching_sha2_password认证的账号如果走非SSL通道会用RSA公钥加密密码再传而客户端请求服务端公钥的流程在老协议里容易失败最终报一个和SSL相关的错误。这时候要么用--ssl-modePREFERRED让连接主动升级为TLS要么给服务器开启公钥自动生成并配置好相关参数。4.2 快速解决SSL连接问题的配置方法先看当前SSL相关状态SHOW VARIABLES LIKE %ssl%; SHOW VARIABLES LIKE tls_version;tls_version如果显示的是TLSv1.2,TLSv1.3那就很明确了老客户端只支持TLSv1.0/1.1的话根本没有协商空间。一个应急方案是在参数文件里放开TLS版本下限[mysqld] tls_versionTLSv1.1,TLSv1.2,TLSv1.3然后重启mysqld。这个操作能让老客户端重新握手成功但同样属于短期缓解老TLS协议的安全性已经在业界公认不行了尽量通过升级客户端来从根本上解决。还有一种情况是你压根不想在测试环境折腾SSL证书就想快速连上库排障。这时可以用命令行参数临时跳过SSLmysql -u root -p --ssl-modeDISABLED或者在客户端连接串里指定mysql -u root -p --skip-ssl这里需要区分一下--skip-ssl在MySQL 8.0的客户端里其实已经废弃了新版本统一用--ssl-mode。--ssl-modeDISABLED会强制不加密连接适合本地测试环境快速接入--ssl-modePREFERRED则是“能加密就加密不能加密就退化”这个才是最省心的日常连接选择。如果是Docker部署的MySQL还需要额外确认容器内证书文件是否挂载正确。经常有人把宿主机的/data/mysql/certs挂载到容器里但没注意my.cnf里的绝对路径和容器内部路径是否一致。Docker日志里如果能看到[Warning] Failed to set up SSL because of missing CA file之类的提示基本都是这个原因。简单处理方式要么补全证书配置并重启要么在容器环境变量或参数里显式关闭SSL需求。4.3 证书文件和“公钥”之间的混淆再辟个谣很多人搜“mysql ssl连接错误”时会看到一堆帖子让关闭SSL。但有一种报错并不是SSL层面的而是RSA公钥获取不到报错长这样ERROR 2061 (HY000): Authentication plugin caching_sha2_password reported error: Authentication requires secure connection.字面意思是“认证需要安全连接”实际上是因为MySQL 8.0.44默认不会再自动把RSA公钥发给客户端除非两个条件之一成立连接走了TLS或者服务端开了caching_sha2_password_auto_generate_rsa_keysON。你的客户端如果既没走TLS、又没拿到公钥自然就报这个错。处理办法很简单在连接命令中指定公钥文件mysql -u root -p --server-public-key-path/path/to/public_key.pem如果你觉得找公钥太麻烦客户端也可以直接用--get-server-public-key参数让它主动向服务端要公钥mysql -u root -p --get-server-public-key这个参数实测下来省事很多尤其在临时排查时比到处找公钥文件高效多了。唯一要提醒的是在正式环境里建议还是走TLS连接尽量避免公钥明文传输带来的隐患。5. 常见问题与排查技巧实录5.1 速查表报错信息、根因与解法对照我在处理8.0.44登录类问题时整理了一个速查表基本覆盖了热词里提到的各种症状现在直接分享出来。报错/症状根因方向快速解法ERROR 1045 (28000): Access denied临时密码未替换 / 认证插件不兼容 / 权限表升级中断查错误日志找临时密码ALTER USER换插件重新执行升级流程ERROR 2002 (HY000): Cant connect through socketsocket路径不一致 / 服务启动失败 / 数据字典版本不匹配统一my.cnf里socket路径查看日志解决MY-014060类错误ERROR 2026 (HY000): TLS/SSL connection errorTLS版本协商失败 / 证书路径错误 / require_secure_transportON指定tls_version允许老版本检查证书文件用--ssl-modePREFERREDERROR 2061 / Authentication requires secure connectioncaching_sha2_password与RSA公钥交互失败用--get-server-public-key或--server-public-key-path[ERROR] [MY-014060] Invalid MySQL server upgrade数据字典版本与二进制版本不一致停止mysqld后用对应版本重新初始化数据目录或做正规升级老Navicat/老驱动连接失败不支持caching_sha2_password升级客户端或临时将账号改回mysql_native_passworddocker容器内连接报错容器端口映射或socket路径未暴露使用-P映射端口用127.0.0.1加端口连接不要依赖socket5.2 两个容易忽略的“隐形坑”第一个坑是并行升级导致的权限表不一致。在从5.7老版本升级时很多人习惯直接下载8.0.44的包替换安装但没注意老版本里的mysql.proc表、mysql.event表、时区表还需要单独处理。8.0版本中这些表不再被数据库内部使用但残留数据会给人一种“数据库没坏只是不能登录”的错觉。正规做法是先备份然后用官方升级工具mysqlcheck -u root -p --all-databases --check-upgrade先跑一遍检查确认无结构错误再尝试登录。实测很多时候所谓的登录报错根子其实在于升级检查没跑数据字典在崩溃状态。第二个坑是系统库的root账户plugin信息在升级后变成了空值。这种情况一般在并行升级或部分升级中出现查询mysql.user表时plugin列可能是空的导致认证走默认规则失败。处理方法很直接UPDATE mysql.user SET plugin mysql_native_password WHERE user root AND host localhost; FLUSH PRIVILEGES;这里要千万注意确认当前版本没有把该列迁移到数据字典表之前再做这步操作8.0环境操作前最好先用SHOW CREATE TABLE mysql.user;确认结构否则会误以为改了张物理表而实际不生效。5.3 RPM安装、Docker安装、源码安装的处置差异这三个安装路径处理登录报错的侧重点完全不同。如果用的是RPM方式升级时往往需要走systemctl restart mysqld流程而SELinux可能在你不知情的情况下阻止了mysqld访问新证书或新socket目录此时系统日志里会出现AVC denied记录。这类问题排查时不要只盯着MySQL错误日志要看/var/log/audit/audit.log和dmesg必要时临时把SELinux设成Permissive模式验证是不是它的问题。如果是Docker方式要特别注意容器内配置文件路径和宿主映射路径不同步。很多人用docker run时把/etc/mysql/conf.d整个挂载进来但容器重启时如果新镜像的配置默认值变了老挂载文件里的参数可能直接导致无法启动。另外容器内的mysql.sock路径一般是/var/run/mysqld/mysqld.sock宿主侧连容器时得走TCP端口而不是本地socket否则必然报2002。如果是源码安装或通用二进制包安装更常见的问题是PATH环境变量里的老版本工具和新版本工具打架。命令行敲mysql时走的是旧版本客户端而服务端已是8.0.44两者协议差异同样会导致登录报错。这种情况执行which mysql mysqld --version对比两个路径来源确保客户端和服务端版本匹配。5.4 升级前必须具备的备份意识最后必须强调一个原则任何登录排查操作都建立在备份基础上。我在处理这类问题时第一步永远是至少做一次逻辑备份或物理备份绝不忍着侥幸心理直接操作。物理备份直接拷贝数据目录或者用官方工具做全量备份都行。对于升级场景尤其注意先备份老版本数据目录和配置文件cp -rp /var/lib/mysql /backup/mysql_5.7_backup_$(date %Y%m%d) cp -p /etc/my.cnf /backup/my.cnf_bak这样就算排查过程中把认证信息改坏了、配置调崩了也能随时回滚到升级前的状态。实测下来很多新手最容易犯的错不是不会改配置而是改之前不备份结果一旦操作失误就彻底大头了。6. 实际操作中的个人体会升级到8.0.44后登录报错说到底是新旧机制切换的一次集中爆发。从处理经验来看最让人头疼的往往不是某一个单纯的故障而是几个问题叠加在一起服务端启动失败、认证插件不支持、SSL协商失败、客户端版本不匹配它们互相干扰表面上看起来像是一个乱成一团的登录问题。我个人现在处理这类问题的顺序已经固定下来第一步看服务状态和错误日志确认服务真的起来了核心看有没有Invalid MySQL server upgrade这样的硬错误第二步用--ssl-modePREFERRED --get-server-public-key这两个参数组合先连上去绕开SSL和公钥问题第三步查mysql.user表确认插件类型然后针对性升级客户端或临时切换插件第四步才是调整SSL策略和TLS版本这些相对深层的配置。这套流程走下来绝大多数登录问题都能在半小时内定位并解决。倒是那些看着不起眼的小事反而更容易让人栽跟头比如临时密码没注意、socket路径认错、容器和宿主配置没对齐。升级这事准备工作做得越细后续排障越轻松。