主从切换时应用连不上新主库本质是应用缓存旧地址或DNS/负载均衡未更新;应使用服务发现、低TTL DNS、禁用JVM DNS缓存、调低HikariCP超时并配重试;重试须幂等,避免INSERT重复;关闭autoReconnect,靠连接池主动检测重建;中间件需监听复制状态变化或切换事件。

主从切换时应用连不上新主库,Connection refused 或 Unknown MySQL server host
本质是应用还缓存着旧主库地址,或 DNS/负载均衡没及时更新。不是数据库没切成功,而是应用“不知道该连谁”。
实操建议:
- 确保应用不硬编码 IP 或域名 —— 改用服务发现(如 Consul)或中间件(如 ProxySQL、MySQL Router)做路由,避免改代码
- 如果用 DNS 做切换,必须设极低 TTL(比如
30秒),且应用层要禁用 JVM 的 DNS 缓存:-Dnetworkaddress.cache.ttl=30 -Dnetworkaddress.cache.negative.ttl=1 - Spring Boot 应用若用
HikariCP,注意hikari.connection-timeout默认是30000(30 秒),切主瞬间大量连接超时会堆积,建议调低到5000并配重试
配置 spring-retry 重试但事务失败后数据重复
重试本身没错,错在没控制重试边界:HTTP 重试 + 数据库写入混在一起,网络超时后应用不确定上次是否已提交。
实操建议:
- 只对幂等操作开启重试,比如
SELECT、UPDATE ... WHERE version = ?;禁止对INSERT或无条件UPDATE直接重试 - 用唯一键(如
order_no)或业务状态机兜底,比如插入前先查SELECT id FROM orders WHERE order_no = ?,存在则跳过 -
@Retryable注解要配合@Recover处理最终失败,别让异常吞掉,否则监控看不到真实失败率
MySQL 客户端连接池自动重连失效,Communications link failure
MySQL 驱动默认关闭自动重连(autoReconnect=false),且即使开也只对单条语句生效,无法解决主从切换后的连接复用问题。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
实操建议:
- 显式关闭
autoReconnect(设为false),靠连接池主动检测和重建更可控 - HikariCP 必须配
connection-test-query=SELECT 1(MySQL 8.0+ 用isValid()) +validation-timeout=3000 - 关键:设置
idle-timeout=60000和max-lifetime=1800000,强制连接在主从切换窗口期(通常 2–5 分钟)内自然淘汰
切主后部分请求仍打到旧主库,Read-only error 或写失败
这是读写分离中间件(如 MyCat、ShardingSphere)或应用自己做的路由没同步刷新元数据,旧连接还在发写请求到只读节点。
实操建议:
- 所有中间件必须监听 MySQL 的
SHOW SLAVE STATUS变化,或订阅 MHA / Orchestrator 的切换 webhook,不能依赖定时轮询 - 应用层自研路由的话,把主库地址存在 Redis 里,切主后立刻
SET master_host new_ip:3306,所有实例监听 key 过期或用 Pub/Sub 主动推送 - 上线前压测要模拟「切主瞬间并发 1000 写请求」,观察错误率是否在可接受范围(比如
),而不是只看平均延迟
最麻烦的从来不是切主动作本身,而是应用连接池、DNS 缓存、中间件元数据这三层缓存怎么协同失效 —— 每一层都可能卡住几秒,叠加起来就超时了。










