MySQL版本升级灰度发布必须依赖Proxy层(如MySQL Router)实现请求级路由,因其能按user_id或Header实时分流、保障读写一致与权限生效,而触发器或应用层if判断会导致读不到数据、主键冲突、权限报错。

MySQL版本升级的灰度发布不能靠改SQL或加触发器实现,必须依赖架构层分流和数据一致性保障机制。直接在应用里写if (isGray())调新库、或用触发器INSERT INTO users_gray,上线当天就会出现读不到数据、主键冲突、权限报错三连击。
为什么 Proxy 层灰度引流是唯一靠谱路径
灰度发布本质是请求级路由控制,而 MySQL 本身不感知“这是灰度用户”。只有在连接建立前就决定走哪套后端,才能保证读写一致、事务完整、权限生效。
- MySQL Router / ShardingSphere-Proxy / Vitess 这类 Proxy 能按
user_id % 100 < 5或 HTTP Header 中的X-Gray-Version做实时路由,且支持自动剔除不可用节点 - 应用完全无感,不用改 DAO、不碰 ORM 配置、不重写存储过程
- 双写阶段可配为「老库全量写 + 新库只读」,避免新库写入未校验导致的数据污染
- 一旦发现
SHOW SLAVE STATUS中Seconds_Behind_Master > 0或Slave_SQL_Running_State卡在Reading event from the relay log,立刻切回老路径,毫秒级止损
影子库同步必须绕开 mysqldump
用 mysqldump --all-databases 导出再导入影子库,8.0 的角色权限、authentication_policy 字段、JSON CHECK 约束全丢光,mysql.user 表直接初始化失败。
- 必须用
mysqlpump --set-gtid-purged=OFF --users --routines(MySQL 5.7.8+ 自带)导出账号与逻辑结构 - 存储过程和函数单独执行
SHOW CREATE PROCEDURE xxx,检查DEFINER是否含@'%'—— 8.0 默认拒绝宽泛 host - 大表同步禁用
mysqldump --single-transaction,改用mydumper -t 8 --trx-consistency-only,它对INSTANT ADD COLUMN兼容更好 - 同步完成后立即验证:
SELECT COUNT(*) FROM mysql.role_edges(5.7 没这表)、SELECT @@default_authentication_plugin是否为caching_sha2_password
切流前必须跑通三类 SQL 行为验证
只测 SELECT 1 和 mysqld --version 就切流,第二天必然爆 GROUP BY 排序错乱、utf8mb4_0900_ai_ci 去重失效、隐式类型转换慢查询。
- 执行
INSERT INTO t VALUES (1, '张三'), (2, '李四')后查SELECT * FROM t WHERE name LIKE '%三%',确认排序规则没让中文搜索漏匹配 - 跑
EXPLAIN FORMAT=tree SELECT * FROM orders WHERE user_id = ?,比对是否多出Using filesort或索引跳过(8.0 默认optimizer_switch='index_merge=on'可能改变执行计划) - 用业务账号执行
SET PERSIST max_connections = 2000,验证 8.0 的持久化变量功能是否启用 —— 若报ERROR 1238 (HY000): Variable 'max_connections' is a read only variable,说明persisted_globals_load=ON没开
最易被忽略的是 GTID 集合校验和 super_read_only 状态。哪怕 Seconds_Behind_Master = 0,如果 SELECT GTID_SUBSET(@@global.gtid_executed, 'xxx') = 0,说明新库根本没收到全部事务;而 super_read_only = OFF 的从库一旦被误写,切主后立刻主键冲突,这种问题不会报错,只会静默损坏数据。


















