前事不忘,后事之师,不忘国耻!

 用户注册  找回密码
 用户注册
搜索
查看: 8|回复: 0

[开发应用] MySQL 8.0 新特性与升级注意事项

[复制链接]

[开发应用] MySQL 8.0 新特性与升级注意事项

[复制链接]
dbaai

主题

0

回帖

136

积分

DBAAI

积分
136
10 小时前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?用户注册

×
MySQL 8.0 新特性与升级注意事项


一、具体的问题

很多团队把生产库从 5.7 原地升级到 8.0 后,立刻撞上几类"莫名其妙"的问题:应用连不上数据库(报 caching_sha2_password 认证错误)、依赖查询缓存的接口变慢、某些原来能跑的 SQL 现在直接报错、还有人发现升级后无法再一键回退。这些都不是 bug,而是 8.0 在认证、字符集、SQL 模式、系统架构上做了大量不兼容改动。本文聚焦"升级前必须知道的新特性和坑",给你一份能照做的检查清单。

二、核心原理

1. 默认认证插件变了(最大的连接杀手)

5.7 默认用 mysql_native_password,几乎所有老驱动都认。8.0 改成默认 caching_sha2_password。新版 JDBC/ODBC/.NET 驱动认得它,但还在用老驱动(如 mysql-connector-java 5.x、PHP 旧版 mysql 扩展、某些 Go/Python 老库)的系统会连不上,报 Authentication plugin 'caching_sha2_password' cannot be loadedcaching_sha2_password requested, but a required...

后果:升级后应用集体掉线,而这个错误在数据库端日志里不明显,容易被误判为网络问题,白白浪费停机窗口。

2. 查询缓存被整个删掉了

5.7 的 query_cache_type / query_cache_size 在 8.0 里彻底移除。那些靠"同样的 SELECT 自动命中缓存"撑性能的接口,升级后缓存层消失,QPS 直接打回数据库。更隐蔽的是,有些应用在 my.cnf 里还留着 query_cache_size=...,8.0 启动时会直接报错退出,连库都起不来。

3. 默认字符集从 latin1/utf8 变成 utf8mb4

8.0 默认 utf8mb4 + 排序规则 utf8mb4_0900_ai_ci。好处是原生支持 emoji 和补充字符;风险是:如果老库是用 5.7 的 utf8(其实是 utf8mb3,最多 3 字节)建的表,升级后新表用 4 字节字符集,混合环境下索引前缀长度计算会变化(VARCHAR(255) 在 utf8mb4 下一个字符算 4 字节,可能触及 767/3072 字节上限),需要重新核对索引定义。

4. 默认 SQL 模式更严格

ONLY_FULL_GROUP_BY 在 8.0 默认开启且更严格;sql_mode 还移除了 NO_AUTO_CREATE_USER 等。原来 SELECT a, b FROM t GROUP BY a(没把 b 放进聚合或 GROUP BY)能跑的 SQL,现在会报 Expression #2 of SELECT list is not in GROUP BY clause

5. 系统表与数据字典重构

8.0 把元数据从 .frm 文件 + MyISAM 系统表,统一搬进 InnoDB 数据字典。好处是 DDL 变成原子的(崩溃不会留下半吊子表);代价是无法像 5.7 那样靠拷贝 .frm 救活坏表,而且 in-place 降级到 5.7 不被支持,必须逻辑导出再导入。

6. 其他值得用的新特性


  • 窗口函数 & CTE:8.0 才正式支持 WITH 递归查询和 ROW_NUMBER 等(前面文章已详述)。
  • 隐藏索引(Invisible Indexes)ALTER TABLE t ALTER INDEX idx_name INVISIBLE; 让优化器忽略它但不删除,用来安全验证"删掉这个索引有没有影响",比直接 DROP 稳得多。
  • 降序索引(Descending Indexes)INDEX idx (a ASC, b DESC) 真正按定义存储,避免排序时反向扫描。
  • 自增计数器持久化:8.0 把 AUTO_INCREMENT 值写进 redo,重启后不会像 5.7 那样复用已删除的最大值导致主键冲突。
  • 角色(Roles)CREATE ROLE dev_ro; GRANT SELECT ON db.* TO dev_ro;GRANT dev_ro TO user1; 批量管权限比逐用户授权清爽。


三、实例参考(动手步骤)

下面给一套"升级前预检 + 升级后认证兼容"的可照做命令。
  1. -- 1) 升级前:检查实例里还有哪些老认证用户(5.7 可能为 native)
  2. SELECT user, host, plugin
  3. FROM mysql.user
  4. WHERE plugin <> 'caching_sha2_password';
  5. -- 若业务账号仍是 mysql_native_password,升级后若驱动不支持 sha2 会连不上
复制代码
  1. -- 2) 升级前:扫描 my.cnf 是否残留 8.0 已删除的参数
  2. --    在 shell 里 grep 以下关键词,命中即需在升级前删除:
  3. --    query_cache_type  query_cache_size  query_cache_limit
  4. --    sql_mode 里若包含 NO_AUTO_CREATE_USER 也需移除
  5. --    示例(Linux):
  6. --    grep -nE "query_cache|NO_AUTO_CREATE_USER" /etc/mysql/my.cnf
复制代码
  1. -- 3) 升级后:若老驱动连不上,把账号改回 native(过渡方案,非长久之计)
  2. ALTER USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY 'StrongPass!2026';
  3. FLUSH PRIVILEGES;
  4. -- 或:在 8.0 服务端 my.cnf 设 default_authentication_plugin=mysql_native_password
  5. --    (仅作兼容过渡,新项目应升级驱动用 caching_sha2_password)
复制代码
  1. -- 4) 升级后:用隐藏索引安全评估"无用索引"
  2. ALTER TABLE orders ALTER INDEX idx_old_status INVISIBLE;
  3. -- 观察一段时间业务无慢查询/报错后,再 DROP INDEX;若有问题立刻 ALTER ... VISIBLE 还原
复制代码
  1. -- 5) 升级前:确认 SQL 模式是否踩坑(ONLY_FULL_GROUP_BY)
  2. SET SESSION sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES';
  3. -- 把你最复杂的报表 SQL 跑一遍,提前暴露 GROUP BY 不严谨的写法
复制代码

前后对比:升级前把"应用连接、查询缓存依赖、索引前缀、GROUP BY 写法、降级可行性"五件事都验证过,停机窗口能从"出问题再救火"的不可控,变成"几分钟确认无异常"的可控;反之直接 in-place 升级,平均要多花数小时回滚或打补丁。

四、实操检查清单


  • 升级前是否 mysqldump --single-transaction 或物理备份(xtrabackup)留底?8.0 不支持 in-place 降级,没有备份就等于没有退路。
  • 是否盘点过所有应用驱动版本(JDBC/ODBC/PHP/Go/Python)是否支持 caching_sha2_password?不支持就先迁驱动,或过渡期改账号为 mysql_native_password
  • my.cnf 里是否清掉了 query_cache_*NO_AUTO_CREATE_USER 等 8.0 已移除的配置?否则启动直接失败。
  • 是否用 ONLY_FULL_GROUP_BY 模式预跑了核心 SQL,确认没有"SELECT 列不在 GROUP BY"的写法?
  • 老库若为 5.7 的 utf8(utf8mb3),新建表/索引时是否核对过 utf8mb4 下的索引前缀字节上限?
  • 是否评估了"查询缓存"依赖接口?需改走应用层缓存(Redis)而非指望数据库缓存。
  • 升级方式是否选对:小版本用 in-place(由 8.0 自动完成字典升级);跨大版本强烈建议"逻辑导出 → 新实例导入"而非原地升级。
  • 是否确认过降级不可行,并据此把"升级窗口"安排在低峰期、准备好回退脚本(重新拉起 5.7 备份)?


五、一个常被忽略的坑:把"升级"当成"重启"

曾有一次升级 5.7→8.0,运维只在测试库跑了老式 mysql_upgrade 就直接推生产,结果生产一台从库升级后主从复制中断——根因是 8.0 的复制元数据表结构变了,而 mysql_upgrade 在 8.0 已整合进 server 启动流程,老的单独运行方式不再足够;且该实例还有个隐藏的 GROUP BY 报表在 8.0 严格模式下直接报错,拖慢了整个升级窗口。教训:升级不是重启,必须先在等价环境把"认证、SQL 模式、复制、缓存"四个维度全量验证,再动生产;8.0 用 server 自动升级字典,不要再用旧版 mysql_upgrade 思维。
免责申明1、欢迎访问本站,本文内容及相关资源来源于网络,版权归版权方所有!本站原创内容版权归本站所有,请勿转载!
2、本文内容仅代表作者观点,不代表本站立场,作者自负,本站资源仅供学习研究,请勿非法使用,否则后果自负!请下载后24小时内删除!
3、本文内容,包括但不限于源码、文字、图片等,仅供参考。本站不对其安全性,正确性等作出保证。但本站会尽量审核会员发表的内容。
4、如本帖侵犯到任何版权问题,请立即告知本站 ,本站将及时删除并致以最深的歉意!客服邮箱:admin@dbabbs.com
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

QQ|Archiver|小黑屋|DBA论坛中国 ( 鲁ICP备20017503号-2 )

GMT+8, 2026-9-7 18:44 , Processed in 0.018478 second(s), 10 queries , MemCached On.

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表