跨数据中心数据库连接需显式配置超时与保活参数:MySQL设connectTimeout=5000&socketTimeout=30000&tcpKeepAliveIdle=45,PostgreSQL设connect_timeout=5&tcp_keepalives_idle=60,并预热DNS、调大连接池超时、启用业务幂等。
连接字符串里必须显式设 connect_timeout 和 read_timeout
跨数据中心时,网络抖动和长尾延迟是常态,tcp 握手或查询响应可能卡在 3–10 秒。mysql 默认的 connect_timeout=10 看似够用,但实际中一旦中间有防火墙、nat 设备或云厂商 slb,握手延迟很容易突破这个值,导致连接直接失败,而不是重试。
PostgreSQL 的 connect_timeout 单位是秒(整数),而 JDBC 的 socketTimeout 是毫秒,容易混淆;MySQL Connector/J 的 connectTimeout 和 socketTimeout 都是毫秒,但命名不统一。
- MySQL 连接串加
?connectTimeout=5000&socketTimeout=30000 - PostgreSQL 连接串加
?connect_timeout=5&tcp_keepalives_idle=60 - JDBC URL 中
socketTimeout控制读超时,connectTimeout控制建连,二者缺一不可 - 不要依赖驱动默认值——不同版本差异大,比如 MySQL 8.0.23+ 把默认
socketTimeout改成了 0(无限)
应用层重试不能只靠 try-catch
单纯捕获 SQLException 或 SocketTimeoutException 后重试,大概率把幂等性搞崩:比如 insert 已发到远端但没收到响应,重试会写两条。
高延迟下,连接池(如 HikariCP)的 connection-timeout 和 validation-timeout 也得调大,否则健康检查本身就会频繁失败,误判连接为失效。
- 写操作必须带业务幂等键(如
idempotency_key字段 + 唯一索引) - 读操作可安全重试,但要限制次数(通常 ≤ 2),避免雪崩
- HikariCP 的
connection-timeout建议设为 8000,比数据库connect_timeout大 3 秒左右 - 禁用
test-on-borrow,改用test-on-create+validation-timeout=5
别让 DNS 解析拖垮首次连接
跨数据中心常通过域名访问 DB(如 db-prod.us-west-2.rds.amazonaws.com),但 DNS TTL 若设得太高(比如 300 秒),且解析服务器又远,首次 getaddrinfo 可能卡住 5 秒以上,且这个时间不被 connect_timeout 控制。
更麻烦的是,某些 JDK 版本(如 OpenJDK 8u292 之前)对 DNS 缓存策略激进,networkaddress.cache.ttl 默认 -1(永久缓存),故障切换后根本刷不过来。
- 应用启动前预热 DNS:执行一次
InetAddress.getAllByName("your-db-host") - 在 JVM 启动参数里加
-Dnetworkaddress.cache.ttl=30 -Dnetworkaddress.cache.negative.ttl=5 - 生产环境优先用内网 IP 或私有 DNS(如 CoreDNS + 自定义 TTL),而非公有云默认域名
- 确认数据库客户端是否支持
useServerPrepStmts=false(MySQL)——开启后预编译语句会额外触发 DNS 查询
长连接保活要穿透所有中间设备
跨 DC 链路中,防火墙、SLB、专线网关普遍有 5–15 分钟的空闲连接清理策略。如果应用只设了 TCP keepalive(Linux 默认 7200 秒),中间设备早把连接掐了,但应用还不知道,下次发包直接报 Broken pipe。
PostgreSQL 的 tcp_keepalives_idle 是从连接建立后算起,而 MySQL 的 net_write_timeout 只管写超时,不管空闲。
- MySQL 加
?tcpKeepAlive=true&tcpKeepAliveIdle=45&tcpKeepAliveInterval=15(需 8.0.29+) - PostgreSQL 推荐
?tcp_keepalives_idle=60&tcp_keepalives_interval=10&tcp_keepalives_count=3 - 应用侧每 3 分钟执行一次轻量心跳(如
SELECT 1),比依赖 TCP 更可控 - 确认云厂商控制台是否开了“连接空闲超时”开关(如阿里云 RDS 的“连接空闲超时时间”默认 3600 秒,需手动调大)










