编程 MySQL 版本号变成四段,VERSION() 还返回三段:巡检、CMDB 和备份命名要改哪几行

2026-10-25 20:02:43

MySQL 版本号变成四段,VERSION() 还返回三段:巡检、CMDB 和备份命名要改哪几行

参考:

现象:同一 patch line 交付多次 update,三段版本区分不出来

MySQL 9.7.4 的发布说明里,Functionality Added or Changed 下有一条 Important Change:服务器开始支持四段式发布标识 MAJOR.MINOR.PATCH.UPDATE,UPDATE 段为空时记为 0。对应 Bug #40013285、WL #17318。

原来的三段版本号能定位到 patch line,但同一 patch line 上分批交付的 update 没有独立标识位。现在有了,问题在于:VERSION() 依旧返回三段。

结果是一批只解析 x.y.z 的东西会得到同一个答案:

  • 巡检脚本采集的版本字段,两次不同的交付写进去一模一样;
  • CMDB 里版本号作为配置项,无法区分具体交付;
  • 备份文件名按版本号拼接,同名覆盖或归档混淆;
  • 发布核对脚本比对“期望版本 vs 实际版本”,永远通过。

这类问题不会抛错,只会让两个不同的东西在记录里长得完全一样,等出问题回头查的时候才发现查不出。

三种新取法,外加客户端库 API

发布说明给出的完整版本获取方式有四种,前三种可以直接在运维脚本里用:

SELECT VERSION_WITH_UPDATE();
SELECT @@version_with_update;
mysqld --version-with-update

VERSION_WITH_UPDATE() 是函数,version_with_update 是只读全局变量,两者拿到的是完整四段版本;mysqld --version-with-update 走二进制侧,不连实例也能取,适合包管理、镜像构建和安装后校验。第四种是新的客户端库 API,供自行封装采集程序时使用。

兼容策略:老接口保持三段语义

新版本没有改老接口的行为。发布说明明确列出保留三段兼容语义的接口:VERSION()、version、classic handshake、numeric version IDs,以及 existing C APIs。

这套做法的直接后果是:老工具不会立刻坏。驱动、连接池、ORM 的版本门禁、依赖握手包判断版本的中间件,输出格式和数字兼容标识的含义都没变,升级到 9.7.4 之后它们照常工作。代价同样明确——它们拿不到 UPDATE 段,只能看到 MAJOR.MINOR.PATCH。

所以这不是“升级后自动变好”的事。要不要拿到 update 段,取决于你的采集链路改没改,而不取决于实例升没升。

mysql_upgrade_history 记录精确 update 迁移

发布说明里另一条:mysql_upgrade_history 记录 exact update transitions,但不改变 upgrade compatibility decisions。

分开看这两半:

  • 记录部分是审计和追溯用途,能查到具体是哪一次 update 迁移过来的;
  • 兼容判断部分没有变,升级路径、可升级性判定仍按原来的语义走。

也就是说,不能指望靠这个文件去改变升级决策逻辑;它是事后可查的证据链,不是升级前置校验的输入。相关的文件格式说明见发布说明里指向的 mysql_upgrade_history File 一节。

该改的几处脚本

采集 SQL。 新版本上直接取四段:

SELECT @@version_with_update AS version_full,
       VERSION() AS version_three_part;

兜底探测。 老版本没有 VERSION_WITH_UPDATE(),直接调用会让监控采集任务报错,而不是回退。先在 shell 里探变量是否存在,变量不存在时 SHOW GLOBAL VARIABLES 返回空结果集,不会报错:

if mysql -NBe "SHOW GLOBAL VARIABLES LIKE 'version_with_update'" | grep -q version_with_update; then
  mysql -NBe "SELECT @@version_with_update"
else
  mysql -NBe "SELECT VERSION()"
fi

改成一条语句时同理,把 SELECT VERSION_WITH_UPDATE() 放在条件分支里,不要让它在老实例上被无条件执行。

采集结果的字段设计。 建议把三段和四段拆成两列存,而不是把四段值塞进原来的版本列。原来的列继续放 VERSION() 的结果,保证依赖它的下游比对逻辑不受影响;新列存 version_with_update,用来做精确区分。老实例上新列为空,下游按空值处理即可,不需要区分“不支持”和“没采到”以外的语义。

备份命名。 需要区分同 patch line 的多次交付时,把 mysqld --version-with-update 的输出拼进文件名或归档路径。只在实例侧拼 VERSION() 的脚本,命名规则要跟着调整。

发布核对。 比对逻辑从“等于期望的三段版本”改成“期望的四段版本等于 @@version_with_update”。注意保留老实例走三段比对的回退分支,否则滚动升级期间核对任务会大面积失败。

哪些场景可以暂时不动

  • 只做功能分支判断的逻辑,比如按 MAJOR.MINOR 决定走哪条 SQL 路径,不需要 update 段;
  • 依赖 numeric version IDs 或 C API 的老组件,语义没变,改它反而增加风险;
  • 升级兼容性判定,mysql_upgrade_history 不改变这块行为;
  • 纯粹的人读场景,比如登录后 SELECT VERSION() 看一眼,暂时够用。

判断标准只有一条:这段逻辑是否需要在同一 patch line 的两次交付之间做区分。需要就改,不需要就先放着。

关于 8.4.13

Oracle 的 2026-10 发布公告里,9.7.4 LTS 和 8.4.13 LTS 是并列的两个维护版本,四段版本号的说明写在 9.7.4 的发布说明条目中。8.4.13 是否同样具备 VERSION_WITH_UPDATE()、@@version_with_update 和 mysqld --version-with-update,需要自行核对 8.4.13 的发布说明后再决定脚本分支,不要按 9.7.4 的行为直接套用。

顺带一提,9.7.4 同时在复制和 InnoDB 面有修复:组复制在网络分区恢复后可能失 quorum 并陷入重连循环(MY-013781),binlogless 副本配合 relay-log recovery 与并行复制时可能出现 mysql.gtid_executed 空洞。这两条和版本号主题无关,升级前照常过一遍发布说明即可。

复制全文 生成海报 MySQL 运维 版本管理 巡检脚本 升级

推荐文章

程序员茄子在线接单