企业出海多云关系型数据库架构实战:AWS RDS/Aurora、阿里云 RDS/PolarDB 与腾讯云 TDSQL 的高可用拓扑、读写分离与分库分表边界(2026最新版)

📅 · 企业出海多云架构实战 - ChengziCloud

一句话结论

关系型数据库是多云架构里少数几个不能靠加机器解决的组件:它同时被事务语义、复制协议和连接模型三件事锁死。

本文要点
  • 前言:本文与既有文章的边界
  • 四个决策变量:把「选型」还原成四个能回答的问题
  • 三云产品族对照:同名不同物
  • 高可用拓扑:从复制协议开始,而不是从产品名开始
  • 读写分离:三类实现,三种完全不同的延迟
  • 连接层:一个被低估的故障源
  • 分库分表:先证明「非分不可」,再谈怎么分
  • 跨云数据分布:冷备、热备,还是双写

关系型数据库是多云架构里少数几个不能靠加机器解决的组件:它同时被事务语义、复制协议和连接模型三件事锁死。这篇长文把「选哪个引擎」拆成四个决策变量——引擎族(自建兼容版 / 共享存储版 / 分布式版)、高可用拓扑(单可用区 / 多可用区主备 / 多可用区集群 / 跨地域)、扩展方式(纵向扩容 / 只读副本 / 分片)、连接模型(直连 / 代理 / 连接池),再逐项对照 AWS RDS 与 Aurora、阿里云 RDS 与 PolarDB、腾讯云 TencentDB 与 TDSQL 的实际能力边界。文中给出故障切换 RTO 的三段拆解、读写分离的延迟陷阱、分库分表的量化判据、一套可复算的成本算例,以及一份按现象定位的排障清单。所有价格只给量级与口径,不做汇率换算后的跨厂商排名。

关键词: 关系型数据库、高可用、读写分离、分库分表、RDS、Aurora、PolarDB、TDSQL、多云架构

一句话答案: 先别比价格,先回答四个问题:写入峰值到底多高、单库能不能扛三年、故障时业务能容忍几分钟不可写、应用能不能改连接串。这四个答案决定引擎族,引擎族决定拓扑,拓扑同时决定账单形态和故障形态。绝大多数误判都发生在第二问——用压测机房的 QPS 去推三年后的容量,而不是用业务增长曲线去推。

前言:本文与既有文章的边界

站内数据方向的文章已经覆盖了「搬」「护」「快」「隔离」,唯独没有覆盖源库本身长什么样。先把边界划清楚,避免把这篇读成某一篇的换皮:

既有文章它解决的问题与本文的边界
09-05 多云数据库跨云同步数据怎么从 A 搬到 B(DTS / DMS / CDC)本文只决定数据放在哪种拓扑上,管道细节归 09-05
09-01 多云数据库安全加固与审计账号、加密、审计日志怎么配本文只把安全当控制点引用,不展开加固步骤
10-09 多云缓存架构怎么用缓存把回源打下去本文讨论被缓存保护的那一层,缓存一致性归 10-09
09-11 备份与勒索软件防护恢复点能不能救回来本文讨论在线可用性,备份保留与不可变归 09-11
10-21 SaaS 多租户隔离租户之间的资源与数据边界本文只说明实例级 / 库级 / 行级三种多租户落在数据库哪一层
09-23 数据治理平台元数据、血缘、质量、数据网格本文讨论引擎与拓扑,治理是它上面的一层
10-24 托管文件存储非结构化共享目录两者正交:一个存表,一个存文件

一句口诀把这几篇串起来:同步管搬运,备份管找回,缓存管少回源,治理管说得清,本文管扛得住。扛得住包含三层意思——故障时能切、流量涨时能扩、连接多时不会被打死。

一、四个决策变量:把「选型」还原成四个能回答的问题

大多数数据库选型讨论之所以吵不出结论,是因为大家在比产品,而产品是多维的。把它压成四个变量之后,讨论会迅速收敛,因为每个变量都有客观输入。

1.1 变量一:引擎族决定天花板在哪

三族的分界线不是「谁更先进」,而是写扩展靠什么:

  • 自建兼容版(Amazon RDS、阿里云 RDS、TencentDB for MySQL):本质是托管了一台主备 MySQL/PostgreSQL。生态最成熟、改造成本最低、SQL 兼容性问题最少,代价是单库容量与写入能力被单机锁死。
  • 共享存储版(Aurora、PolarDB、TDSQL-C):计算与存储分离,所有节点共享同一份分布式存储,只读节点不复制数据页、只回放日志。读扩展快、副本延迟低、扩容不用搬数据,但写入仍然只有一个写节点,写放大问题没有消失。
  • 分布式版(PolarDB-X、TDSQL 分布式版、基于 ShardingSphere 的自建分片):把数据水平切开,写能力随分片数线性增长。代价是跨分片 JOIN、分布式事务、全局二级索引、扩容重分布这四件事都要单独设计。
维度自建兼容版共享存储版分布式版
写扩展方式纵向加规格纵向加规格加分片(近线性)
读扩展方式异步只读副本共享存储只读节点只读节点 + 分片副本
单库容量上限受单机磁盘与备份窗口限制大(自动增长,上限以官方为准)理论无上限
应用改造量几乎为零低(连接串与只读地址)高(分片键、跨片查询、事务)
典型故障形态主备切换、复制延迟存储层多副本自愈单分片热点、跨片事务悬挂
适合谁中小规模、迁移优先读多写少、要求快速切换写入极高、单库确定要炸

1.2 变量二:高可用拓扑由 RTO 目标反推

拓扑不是越贵越好,而是先定 RTO/RPO,再选最便宜的那一档。四档常见形态:

  1. 单实例 + 快照:RTO 小时级(要重建实例、回放备份),RPO 等于上次备份点。只适合内部工具。
  2. 多可用区主备:同步或半同步复制,主库故障自动切到备库,RTO 分钟级,RPO 接近零。
  3. 多可用区集群(一写两读备):半同步 + 两个可读备节点,切换更快,且备节点能承接只读流量。
  4. 跨地域:异地副本或全球数据库,应对的是区域级故障,RTO 分钟到小时,RPO 秒级,成本最高。

1.3 变量三:扩展顺序不能颠倒

正确的顺序是先纵向、再读写分离、最后分片。原因很朴素:纵向扩容改一个规格参数、零代码改动;读写分离改的是连接串和少量路由逻辑;分片改的是数据模型,一旦分片键选错,回退成本接近重做。

跳过前两步直接分片的团队,绝大多数在半年后发现:写入 QPS 只涨了两倍,但跨分片查询和分布式事务带来的复杂度已经把团队吞掉。

1.4 变量四:连接模型是最容易被忽略的一层

单体应用时代,一个应用进程一条连接池就够。容器化 + Serverless 之后,实例数会在几分钟内从 20 涨到 200,每个实例开 20 条连接,数据库侧的连接数瞬间打满,表现为「CPU 不高、内存不高,但新连接全部超时」。

连接层的三种解法:应用内连接池(HikariCP / PgBouncer)、数据库代理(RDS Proxy、PolarDB 代理、TDSQL 数据库代理)、以及把长连接改成短事务。选择依据是连接数是稳定的还是脉冲式的——脉冲式必须上代理。


写入峰值 ──▶ 能不能单库扛三年?──否──▶ 分布式版(先设计分片键)
                    │是
                    ▼
            读 QPS 是否远大于写?──是──▶ 共享存储版 + 只读节点
                    │否
                    ▼
            RTO 要求 < 1 分钟?──是──▶ 多可用区集群 / 三节点
                    │否
                    ▼
                 多可用区主备(性价比最高的一档)

二、三云产品族对照:同名不同物

下面这张表是本文的地基。注意最后两列——同名产品在不同云上的实现模型可能完全不同,这是跨云架构里最容易踩的坑:把 Aurora 的「读副本零数据复制」经验直接套到 RDS 只读副本上,会得到完全错误的延迟预期。

产品引擎族存储与复制模型只读扩展上限最适合主要约束
Amazon RDS(MySQL / PostgreSQL / MariaDB)自建兼容实例本地 EBS,多可用区为同步复制MySQL/PG 最多 15 个只读副本迁移优先、兼容性优先单库容量与写 QPS 受单机限制
Amazon RDS(SQL Server / Oracle)自建兼容同上5 个只读副本传统商业数据库上云许可与 BYOL 条款另算
Amazon Aurora MySQL / PostgreSQL共享存储6 份副本跨 3 个可用区,日志即数据库15 个只读副本读多写少、要求秒级切换写入仍单节点;I/O 按请求计费
Aurora Serverless v2共享存储 + 弹性算力以 ACU 为粒度伸缩同 Aurora波动负载、开发测试环境缩容有冷却时间,持续高写不划算
阿里云 RDS MySQL 高可用版自建兼容主备跨可用区,半同步只读实例(上限随规格)传统业务上云主备切换期间有秒级不可写
阿里云 RDS 三节点企业版自建兼容 + 三副本一主两备,同城三可用区只读实例金融级 RPO=0成本显著高于双节点
阿里云 PolarDB MySQL 版共享存储计算存储分离,存储多副本最多 15 个只读节点读扩展 + 大容量单库写单节点;需正确配置代理
阿里云 PolarDB-X分布式计算节点与存储节点分层随分片水平扩展高并发写入、透明分库分表跨分片查询有额外开销
腾讯云 TencentDB for MySQL(双节点 / 三节点)自建兼容主备异步/半同步;三节点强同步只读实例通用业务、政务三节点成本更高,网络要求更严
腾讯云 TDSQL-C MySQL 版共享存储计算存储分离最多 15 个只读节点读扩展、快速弹性存储按量计费,需盯住增长
腾讯云 TDSQL(分布式)分布式水平拆分 + 强同步随分片水平扩展金融核心、海量写入分片键设计决定一切

读这张表要抓住三个不对称:

  • 只读副本的语义不对称:RDS 只读副本是异步复制 binlog,Aurora 与 PolarDB 的只读节点共享存储、只回放日志。前者延迟随写入量波动(大事务能拖到几十秒),后者通常在毫秒到百毫秒量级。所以「加只读副本解决读压力」这句话,在三族里的含义完全不同。
  • 故障切换的机制不对称:多可用区主备靠 DNS 切换 + 备库提升,客户端要重连;共享存储版靠存储层选主,切换更快但仍有连接中断。
  • 计费维度的不对称:自建兼容版按「实例规格 + 存储 + 备份」计费;共享存储版多出「I/O 请求数」这一维;分布式版还多出「分片数 × 节点规格」。第三种的账单最难预测,因为分片数会随业务增长被动增加。

口径说明:本节的「上限」均为能力级描述,具体规格(最大存储、最大连接数、只读节点上限随规格的变化)以各厂商当期文档为准。文中不引用未核实的精确数字,宁可口径保守,也不印一个可能过期的上限。

三、高可用拓扑:从复制协议开始,而不是从产品名开始

高可用的实际表现由复制协议决定,产品名只是包装。三种协议对应三种故障形态,先把它们分开。

3.1 三种复制协议的真实差别

协议提交返回时机RPO写延迟代价失效模式
异步复制主库本地提交后立即返回可能丢最后一段事务几乎为零主库宕机丢失未同步 binlog
半同步复制至少一个备库收到并落盘日志后返回接近零(取决于等待点)增加一次跨可用区往返备库无响应时退化为异步
强同步 / 多数派多数派副本确认后返回零增加多次往返少数派故障不影响提交

半同步有一个必须知道的细节:MySQL 的半同步插件在等待超时后会静默退化为异步。默认超时是 10 秒,也就是说备库网络抖动超过 10 秒,主库会继续接受写入,此时的 RPO 已经不再为零,但监控面板上一切正常。这就是为什么「我们开了半同步」不等于「我们 RPO=0」——要盯的是退化事件,不是开关状态。

MySQL 8.0.26 之后,半同步的变量名从 master 改为 source,等待点默认是 AFTER_SYNC(事务在引擎层提交前等待备库确认),比旧版的 AFTER_COMMIT 少一个「主库已提交但备库未收到」的窗口。做跨云复制评估时,这一项要单独确认,因为它直接决定切换后会不会出现主备数据分叉。

3.2 四档拓扑的量化对照

拓扑复制方式RPORTO(经验值)相对成本适用场景
单实例 + 定时快照无上次快照点小时级1.0内部系统、可重建数据
多可用区主备同步(AWS 多可用区实例)/ 半同步≈0通常 1–2 分钟≈2.0绝大多数生产业务
多可用区集群(一写两读备)半同步≈0通常 35 秒内≈2.5–3.0切换敏感、备节点可分担只读
同城三副本(三节点企业版)强同步(多数派)0秒级到 1 分钟≈3.0金融、政务、有明确 RPO=0 要求
跨地域(全球数据库 / 异地灾备)物理复制 / 异步秒级分钟到小时4.0 以上区域级故障、跨境业务

表中 RTO 是厂商公开口径与工程经验叠加的量级,不是 SLA 承诺。真实 RTO 一定比你想象的长,因为切换只完成了「数据库能写」,没有完成「应用能连」。

3.3 把 RTO 拆成三段,才知道该优化哪里

线上事故里最常见的误判,是把数据库的切换时间当成业务恢复时间。实际 RTO 是三段之和:


检测故障 ──▶ 选主与提升 ──▶ 客户端重连与预热
  (10~60s)      (10~40s)        (30s~5min)
  • 检测段:依赖健康检查间隔与失败阈值。调得太灵敏会误切(网络抖动就切),太迟钝会拖长不可用时间。经验值是连续 3 次失败、间隔 10 秒。
  • 选主段:厂商托管,多可用区主备通常 60–120 秒,多可用区集群可压到 35 秒内,共享存储版通常在 30 秒量级。
  • 重连段:这是自建方案里最容易被忽略、也最容易爆炸的一段。DNS 缓存未过期、连接池里全是死连接、JVM 里的旧连接对象没有失效检测,应用会在数据库已经恢复之后继续报错几分钟。这一段只能靠应用侧解决:连接池开启 validationTimeout 与 keepaliveTime,DNS 记录 TTL 调到 30 秒以内,重试带指数退避。

一个反直觉的结论:优化重连段通常比升级数据库拓扑更划算。把 RTO 从 120 秒压到 35 秒要多花一倍钱;把重连段从 5 分钟压到 30 秒只需要改几行连接池配置。

3.4 多可用区不等于跨云容灾

这是多云架构里最贵的认知错误。三种「高可用」应对的是三种完全不同的故障:

故障类型多可用区能救跨地域能救跨云能救
单台物理机 / 单可用区故障能能能
区域级故障(地震、区域网络)不能能能
云厂商账号级故障(欠费、误删、管控面故障)不能不能能
厂商级产品缺陷(内核 bug、批量重启)不能部分能能

如果你的合规要求写的是「业务连续性」,多可用区就够了;如果写的是「厂商级风险隔离」,那必须跨云。而跨云的代价不是多一份实例钱,而是双写一致性与切换决策权——这部分本文第八节展开。

3.5 切换演练:不演练的高可用等于没有

托管数据库的切换能力是厂商给的,但你的应用能不能接住只有演练能验证。建议的节奏:

  • 每季度一次计划内切换演练,选业务低峰,提前通知上下游。
  • 每次演练记录四个数字:检测耗时、切换耗时、首笔成功事务时间、错误率回到基线时间。
  • 演练后必须复盘「重连段」,这一段几乎每次都能发现新问题(缓存了旧 IP 的服务、没有重试的定时任务、只连一次的消息消费者)。

一个可直接抄的判据:如果团队说不出上一次切换演练的日期,那么这个高可用拓扑在事故当天的表现,等同于单实例。

四、读写分离:三类实现,三种完全不同的延迟

「加只读副本」是数据库扩容里最常见、也最容易做错的一步。做错的原因不是配置,而是没搞清楚读到的数据可能是旧的。

4.1 三种实现路径

实现层代表方案路由灵活性一致性控制主要代价
应用层多数据源 + AOP / 注解路由最高(可按业务强制走主)自己实现代码侵入,容易漏配
中间件层ProxySQL、MaxScale、MyCat、云厂商数据库代理中(按 SQL 类型或权重)代理提供一致性级别多一跳网络,代理本身要 HA
数据库内核Aurora 只读副本与 reader endpoint、PolarDB 只读节点、TDSQL-C 只读实例低(按 endpoint 轮询)依赖复制延迟无法按业务语义区分

三个容易搞错的点:

  • Amazon RDS Proxy 不做读写分离。它的职责是连接池、故障切换加速和 IAM 认证,读流量仍然打到你给它的那个 endpoint。想要读写分离,得自己用只读副本 endpoint 或上中间件。
  • Aurora 的 reader endpoint 是轮询,不感知复制延迟。也就是说一个落后 30 秒的只读副本照样会被分到读流量。要按副本规格或负载分流,得用自定义 endpoint 分组。
  • 云厂商的数据库代理通常提供「一致性级别」开关。会话一致性会在写后一段时间内把该会话的读强制回主库,全局一致性则更保守——级别越高,回主库的读越多,主库压力越大。这是典型的「一致性换吞吐」旋钮,不是免费开关。

4.2 复制延迟到底从哪来

只读副本的延迟不是均匀分布的,它有四个典型来源:

  1. 大事务:一条影响百万行的 UPDATE,在主库上是一条语句,在备库上要回放百万行。期间延迟曲线是一条尖峰,能到几十秒。
  2. DDL:加索引、改字段类型这类操作在主库上可能是 Online DDL,但在备库上是单线程回放,大表能堵几分钟。
  3. 并行回放能力:MySQL 5.6 按 schema 并行,单库业务等于没有并行;5.7 起按组提交(LOGICAL_CLOCK)并行;8.0 默认 WRITESET,冲突检测更细,并行度更高。从 5.6 升到 8.0,最直接的收益之一就是复制延迟显著下降。
  4. 备库规格不足:主库 8 核、备库 4 核,写入一高备库就先顶不住,延迟随负载线性上升。

监控上,Seconds_Behind_Source(旧版本叫 Seconds_Behind_Master)精度只到秒,而且在大事务期间会显示 0(因为它按最后一个已执行事件的时间戳计算)。更可靠的指标是 performance_schema.replication_applier_status_by_worker 里的 APPLYING_TRANSACTION 位置差,以及 MySQL 8.0 的 replication_applier_status_by_coordinator。


-- 秒级延迟,NULL 表示复制线程已中断
SHOW REPLICA STATUS;

-- 细粒度:每个 worker 正在回放哪个事务
SELECT WORKER_ID, APPLYING_TRANSACTION, LAST_APPLIED_TRANSACTION
FROM performance_schema.replication_applier_status_by_worker;

-- 长事务造成的 purge 阻塞,历史列表长度持续上涨说明有大事务
SHOW ENGINE INNODB STATUS;

4.3 哪些读必须强制走主库

场景是否必须走主原因
写入后立即跳转详情页是(或会话粘滞 N 秒)用户会看到自己刚改的数据没生效
支付回调后的订单状态查询是状态机判断依赖最新值,读到旧值会重复处理
库存扣减后的余量展示是超卖投诉的常见来源
幂等校验(查唯一键是否存在)是备库还没回放,幂等直接失效
列表页、报表、导出否可容忍秒级延迟,且是读放大的主力
全文检索类查询否建议直接放搜索引擎,不要压数据库

工程上最省事的做法是会话粘滞:同一会话在写操作后的 N 秒内(N 取该业务可接受的最大延迟,通常 1–5 秒)全部走主库,之后恢复读分流。它比「按 SQL 语义判断」实现简单得多,也几乎不会漏。

4.4 只读副本的成本不止实例费

三个隐藏成本:

  • 每个副本都是一份完整实例费。共享存储版稍好(不复制数据页,存储只算一份),自建兼容版则是每个副本一份存储 + 一份计算。
  • 跨地域副本的复制流量单独计费,量级是每 GB 几分美元。一个日增 50 GB 的库,跨区复制一个月就是 1.5 TB 的出流量。
  • 备份与快照成本随副本数上升(部分厂商只对主实例做自动备份,副本不额外计费,需逐家确认)。

所以正确的做法不是「读不够就加副本」,而是先看读流量里有多少是可以缓存的、多少是可以走搜索引擎的、剩下多少才真正需要数据库只读节点。10-09 那篇缓存架构讲的正是前两步。

五、连接层:一个被低估的故障源

数据库连接是有状态、有内存、有上限的资源。它不像无状态的 HTTP 请求,加个负载均衡就完事。连接层的容量算错,表现通常是「数据库监控一片绿,业务全线超时」。

5.1 先算清楚需要多少连接

经验公式是:并发连接数 ≈ 峰值 QPS × 平均事务耗时(秒)。注意是峰值,不是均值,也不是「QPS 除以单连接能扛的 QPS」。

举例:峰值 3,000 QPS、平均事务 8 毫秒,那么理论上同时占用连接的请求约 24 个。考虑到突发与长事务,连接池开 50 足够。但很多团队按「1000 QPS 就开 1000 连接」来配,结果是数据库把大量内存花在连接缓冲上,缓存命中率下降,性能反而更差。

连接池大小的经典起点是 HikariCP 的建议公式:连接数 = CPU 核数 × 2 + 磁盘数。4 核数据库配 9–12 条连接,听起来少得离谱,但在 OLTP 场景下往往比 200 条连接吞吐更高——因为连接一多,锁竞争和上下文切换就会吃掉收益。

5.2 每条连接要花多少内存

MySQL 每条连接的内存占用由会话级缓冲决定,典型项包括 read_buffer_size、sort_buffer_size、join_buffer_size、binlog_cache_size。空连接只占几百 KB,但活跃连接在排序、JOIN 时会各自分配缓冲区,峰值可以到每条 5–10 MB。

于是出现一个反直觉现象:连接数上限设成 2,000,实际能安全承载的活跃连接可能只有 300——超过之后不是报「连接数超限」,而是内存吃紧、swap、响应时间雪崩。连接数上限应该按内存倒推,而不是按最大值配。

5.3 四种连接层方案的取舍

方案作用适合不适合注意
应用内连接池(HikariCP / Druid)复用连接、检测失效单体或实例数稳定的服务实例数剧烈波动的场景每个进程一份池,实例数一涨连接数线性上涨
PgBouncerPostgreSQL 连接复用,模式可选大量短连接、函数计算依赖会话状态的应用transaction 模式下 prepared statement 与 advisory lock 有坑
云数据库代理(RDS Proxy / PolarDB 代理 / TDSQL 代理)连接池 + 故障切换加速 + 读写分离Serverless、容器弹性伸缩强依赖会话变量的老应用代理本身要开多可用区,否则它成为新单点
中间件(ProxySQL / MaxScale)读写分离、查询缓存、连接多路复用自建 MySQL 集群无专职 DBA 的团队多一跳网络,规则配置出错会放大故障

PgBouncer 的三种池模式值得单独记住,因为选错会引发极难排查的 bug:

模式连接归还时机兼容性典型故障
session会话结束最好连接复用率低
transaction事务结束较好会话级 SET、临时表、advisory lock 会跨事务串味
statement每条语句结束最差显式事务直接失效

transaction 模式最常用,但它把「会话」压缩成了「事务」,任何依赖会话状态的东西都会出问题——包括 SET search_path、SET timezone、临时表、以及某些 ORM 的 prepared statement 缓存。这也正是 10-21 那篇多租户文章里 RLS 泄漏的同类根因:连接被复用,但会话状态没有被重置。

5.4 Serverless 与弹性扩容下的连接风暴

函数计算、Kubernetes HPA、Serverless 容器有一个共同特征:实例数在几十秒内成倍变化。每个新实例启动时都会建连接,旧实例缩容时连接不会立刻释放(TCP 层还在 FIN_WAIT)。两个方向叠加,数据库侧看到的连接数会出现远超业务量的尖峰。

三道防线:

  1. 代理前置:所有弹性工作负载统一走数据库代理,应用侧看到的是代理的连接,真实连接数被池化。
  2. 连接上限 + 排队:在代理或连接池上设硬上限,超出的请求排队而不是直接失败,配合超时快速失败,避免请求堆积。
  3. 缩容优雅退出:实例收到终止信号后先归还连接再退出,把 terminationGracePeriodSeconds 设得比连接池的 maxLifetime 长一点。

5.5 连接泄漏怎么定位

连接泄漏的表现是「连接数缓慢上涨、几天后打满、重启应用就好」。定位靠三张表:


-- MySQL:按来源 IP 与状态聚合,找出只增不减的连接
SELECT SUBSTRING_INDEX(HOST, ':', 1) AS client_ip, COMMAND, COUNT(*) AS conns
FROM information_schema.PROCESSLIST
GROUP BY client_ip, COMMAND
ORDER BY conns DESC;

-- 找出空闲时间最长的连接(SLEEP 时间即空闲秒数)
SELECT ID, USER, HOST, DB, TIME, STATE FROM information_schema.PROCESSLIST
WHERE COMMAND = 'Sleep' ORDER BY TIME DESC LIMIT 20;

-- PostgreSQL:按应用名与状态聚合
SELECT application_name, state, count(*) FROM pg_stat_activity
GROUP BY application_name, state ORDER BY count(*) DESC;

如果 Sleep 状态的连接集中在某个应用名上,基本可以断定是那边的连接池没有正确关闭,或者 maxLifetime 设成了无限。

六、分库分表:先证明「非分不可」,再谈怎么分

分片是数据库架构里唯一基本不可逆的决策。分片键选错,回退成本接近重做一次业务。所以这一节的重点不是「怎么分」,而是「怎么证明现在还不该分」。

6.1 先排除三种不需要分片的情况

在讨论分片之前,先确认下面三件事都做完了:

  1. 索引是否真的对。慢查询日志里 80% 的问题来自缺失索引或索引失效(隐式类型转换、函数包裹列、最左前缀断裂),这些都能通过加索引解决,不需要动数据模型。
  2. 冷数据是否归档。订单表 5 亿行里,往往 80% 是两年前的只读数据。把它们迁到归档库或对象存储,主表立刻瘦身,效果比分片更直接。
  3. 是否可以用分区表。MySQL 8.0 与 PostgreSQL 都支持原生分区,按时间分区后,历史分区可以独立归档、独立 DDL,运维成本远低于应用层分片。

这三步做完仍然不够,才轮到分片。

6.2 量化判据表

信号经验阈值为什么它是信号
单表行数2,000 万 ~ 1 亿B+ 树层数从 3 层涨到 4 层,每次查询多一次随机 I/O
单库存储2 ~ 4 TB备份窗口、DDL 时长、恢复时间都随容量线性恶化
写入 QPS持续超过单实例上限的 60%留 40% 余量给突发与主备切换后的单点承压
单表 DDL 耗时超过 30 分钟意味着任何结构变更都需要停业务窗口
连接数持续超过上限的 70%分片后连接数会按分片数成倍增长,先解决连接层
单表索引大小超过内存的 50%索引无法全部缓存,随机读性能断崖

关键点是:行数不是唯一信号。一张 5,000 万行但只按主键查的表,往往比一张 500 万行但有 8 个二级索引、写入频繁的表更健康。

6.3 分片键决定一切

分片键优点缺点适用
用户 ID / 租户 ID同一用户数据聚合,事务在单分片内完成大客户会造成分片倾斜(热点租户)SaaS、面向 C 端的账户体系
订单 ID(雪花)写入均匀按用户查订单要扫全部分片订单中心(配合基因法)
时间归档方便,旧分片可下线写热点永远在最新分片,等于没分日志、流水类只写少查
商户 ID商户维度查询快头部商户热点电商平台侧
哈希(手机号 / 邮箱)均匀范围查询失效用户中心

两个必须掌握的技巧:

  • 基因法:把用户 ID 的低位比特嵌入订单 ID,使「按订单 ID 查」和「按用户 ID 查」落到同一分片。代价是 ID 生成器要改造,收益是省掉一张「订单-用户」映射表。
  • 热点租户隔离:分片键是租户 ID 时,头部租户会独占一个分片。解法是给大租户单独指定物理分片,其余租户按哈希分布——这就是 10-21 那篇里 Pool / Bridge / Silo 模型在数据库层的投影。

6.4 分片之后必须重写的五件事

问题表现常见解法
跨分片 JOIN查询变慢或报错冗余字段、宽表、把 JOIN 移到应用层
聚合与排序分页ORDER BY ... LIMIT 结果错乱各分片取前 N 再归并;深度分页改用游标
分布式事务跨片写入不一致尽量避免跨片事务;必须时用 Saga 或 TCC
全局唯一 ID自增主键冲突雪花算法 / 号段模式 / UUIDv7
扩容重分布数据搬迁期间双写预分逻辑槽(如 1024 槽),扩容只搬槽不重算

预分槽是最值得提前做的一件事:一开始就把数据分成 1,024 个逻辑槽,物理上放在 4 个库,每个库 256 槽。将来扩到 8 个库,只需把每个库的一半槽搬走,路由规则不变,搬迁量可控。相比之下,「按 id % 4 直接取模」在扩容到 8 库时,几乎每条数据都要换位置。

6.5 中间件与分布式数据库怎么选

方案形态侵入性分布式事务运维负担适合
ShardingSphere-JDBC客户端 SDK高(改依赖与配置)支持(XA / BASE)低(无额外组件)Java 技术栈、团队有能力改代码
ShardingSphere-Proxy独立代理低(当成 MySQL 用)支持中(代理要 HA)多语言、不想改应用
Vitess代理 + 管控面低有限支持高大规模 MySQL、有平台团队
PolarDB-X托管分布式数据库低(兼容 MySQL 协议)支持低(厂商托管)已在阿里云、想少运维
TDSQL 分布式版托管分布式数据库中(需设计分片键)强一致低金融核心、强一致要求

选择逻辑很清晰:团队有没有能力自己运维分片中间件。有能力,ShardingSphere 或 Vitess 更灵活、不被厂商绑定;没有能力,托管分布式数据库的综合成本更低,代价是迁移成本随数据量上升。

6.6 一条务实的路线


索引优化 + 慢查询治理(1~2 周)
        │ 仍不达标
        ▼
冷数据归档 + 分区表(2~4 周)
        │ 写入仍打满
        ▼
读写分离 + 连接代理(1~2 周)
        │ 写入仍打满
        ▼
预分槽分片 / 分布式数据库(1~3 个月,需专项)

跳过前三步直接做第四步的团队,通常会在分片完成后发现:慢查询还在,只是从「单表慢」变成了「跨片更慢」。

七、跨云数据分布:冷备、热备,还是双写

多云的数据库层绕不开一个选择:第二个云上的那份数据,是备着还是在用。这三档的差别不在技术难度,而在一致性责任由谁承担。

7.1 三种形态

形态复制方式RPORTO一致性责任成本倍数
冷备定时全量 + binlog 归档到对象存储小时级数小时(要重建实例再回放)厂商1.1 ~ 1.3
温备 / 热备异步或半同步复制到另一云的实例秒级分钟级(提升副本)厂商 + 你的切换脚本2.0
双活双写两个云都能写冲突时才可见秒级你的应用2.5 以上

第三档看起来最美,实际最难。原因在 7.2。

7.2 为什么数据库双写几乎总是错的

  • 冲突没有通用解。两个云同时改同一行,最后写的赢?按时间戳?按版本号?任何策略都要业务定义,而业务往往说「不应该发生」。它会发生。
  • 自增与序列冲突。两边都用自增主键,迟早撞号。改成号段或雪花之后,又引入时钟回拨问题。
  • 事务边界被撕裂。一个事务里写了订单表和库存表,两张表分处两个云,本地事务变成分布式事务,延迟从毫秒变成几十毫秒。
  • 跨云延迟放大了锁持有时间。同区域内跨云 RTT 通常在几毫秒,跨地域 50–200 毫秒。一个持有行锁 3 次的写事务,在跨云双写下可能持锁几百毫秒,锁等待迅速堆积。

所以工程上更常见的做法是「单写多读」:写只落一个云,另一个云只提供读与灾备接管。切换是单向的、有明确决策点的,而不是两边同时活着。

7.3 单元化:把「跨云」变成「跨单元」

真正能同时拿到低延迟与故障隔离的,是单元化:按用户 ID 或租户 ID 把流量与数据切成一闭环的单元,每个单元内部自洽(应用 + 数据库 + 缓存),跨单元只做异步数据同步(通常是用户维度的镜像或汇总)。

这里要和 10-02 那篇划清边界:那篇讲的是部署拓扑与故障域收敛,本文讲的是数据怎么按这个拓扑切分与路由。两者是同一件事的两面,顺序上应该先定单元边界,再决定每个单元用哪种数据库拓扑。

单元化的代价是「跨单元查询」:全局报表、全局搜索、跨单元转账都要额外设计。所以它适合用户维度天然可切的业务(社交、SaaS、电商买家侧),不适合全局强一致的账务核心。

7.4 跨云复制的五个检查点

检查点要确认什么典型坑
复制延迟常态延迟与峰值延迟分开看只看均值,忽略大事务尖峰
带宽成本每日增量 × 跨区单价忘了索引变更会带来额外 binlog 量
DDL 同步结构变更怎么同步到对端主库 Online DDL,备库阻塞回放
字符集与时区两端必须一致一端 utf8 一端 utf8mb4,表情符号写入失败
自增与序列切换后是否连续、是否冲突双写时撞号,单写时切换后跳号被当成 bug

一个常被问的问题:跨云热备的 RTO 到底是多少?答案取决于你的切换脚本,而不是数据库。数据库提升副本可能只要 1 分钟,但改 DNS、改连接串、验证应用、回滚预案,通常是 30 分钟到 2 小时。把这段写进预案,比优化数据库切换时间更有价值。

八、兼容性评估:迁移前必须逐项打勾的八件事

跨云或从自建迁到托管,出问题的地方几乎从不是「SQL 跑不起来」,而是这些边角:

项目要确认的细节出问题的表现
版本5.7 还是 8.0,小版本差异8.0 默认 utf8mb4_0900_ai_ci 排序规则,与 5.7 的 utf8mb4_general_ci 结果不同
字符集库、表、列、连接四层是否统一只有连接层是 utf8,插入 emoji 报错
排序规则大小写敏感、重音敏感唯一索引在两端判重结果不一致
存储引擎InnoDB 为主,是否有 MyISAM 遗留表MyISAM 不支持事务,迁移后行为变化
SQL 方言LIMIT、IFNULL、GROUP BY 严格模式ONLY_FULL_GROUP_BY 打开后老 SQL 直接报错
存储过程 / 触发器 / 事件是否有、是否需要 DEFINER 权限迁移工具跳过或执行失败
权限模型账号、角色、GRANT 语法迁移后应用账号权限不足
时区服务端、会话、应用三处时间字段偏移 8 小时

最容易被低估的是排序规则。它不影响功能测试,只影响 WHERE name = 'abc' 能不能命中、唯一索引会不会误判重复。上线后表现为「偶发重复注册」「查询少一条」,排查成本极高。

评估的做法不是读文档,而是跑一遍真实 SQL:把生产慢查询日志里的 Top 200 条 SQL 拿到目标实例上 EXPLAIN,对比执行计划与耗时。这一步通常能在半天内暴露 90% 的兼容性问题。

九、上线前必须做的四个压测

压测的目的不是拿到一个漂亮的 QPS 数字,而是知道系统在什么条件下开始不线性。四个必做项:

9.1 四项压测

压测怎么做要回答的问题
基准 OLTPsysbench 读写混合,逐步加压到拐点单实例的真正吞吐上限在哪
写入尖峰固定并发,突增 3 倍写入并维持 5 分钟复制延迟会不会失控,连接池会不会打满
主备切换主动触发托管实例的故障切换,全程打流量应用要多久恢复,错误率曲线长什么样
大查询干扰在压测中并发跑一条大报表 SQL一条慢查询会把整体 P99 拖到什么程度

sysbench 的常用组合(数据量要大于内存,否则缓存全命中,结果没有参考价值):


sysbench oltp_read_write --db-driver=mysql --mysql-host=HOST --mysql-user=USER \
  --mysql-password=PASS --mysql-db=sbtest --tables=20 --table-size=5000000 \
  --threads=64 --time=300 --report-interval=10 prepare

sysbench oltp_read_write --db-driver=mysql --mysql-host=HOST --mysql-user=USER \
  --mysql-password=PASS --mysql-db=sbtest --tables=20 --table-size=5000000 \
  --threads=64 --time=300 --report-interval=10 run

9.2 看四个指标,不看平均值

  • P99 而非平均:平均值永远好看,用户感知的是尾部。
  • 复制延迟峰值:压测期间的 Seconds_Behind_Source 最大值,比均值重要一个数量级。
  • 连接数:是否触到上限,是否出现排队。
  • IOPS 饱和度:gp3 的基准 IOPS 是 3,000、基准吞吐 125 MiB/s,超出后靠突发积分,积分耗尽就掉速——这正是「压测很好、上线三天变慢」的典型原因。

9.3 四个压测陷阱

  1. 数据量太小:100 万行全在 buffer pool 里,等于在测内存。
  2. 只有均匀分布:真实业务有热点(大客户、爆款商品),均匀压测测不出热点行锁。
  3. 忽略复制:只压主库,上线后才发现只读副本延迟 30 秒。
  4. 用 SELECT 1 测连接上限:连接建立与查询执行是两条路径,前者测不出后者的内存问题。

十、成本模型:四个维度与四个隐藏项

云数据库的账单从来不是「一台机器的钱」。它是四个维度的乘积:计算(规格 × 节点数 × 时长)+ 存储(容量 × 单价)+ I/O(请求数,仅共享存储版)+ 附加(备份、跨区流量、日志、监控)。

10.1 算例:同一套业务,两种引擎族

假设业务需要:4 vCPU / 32 GiB 主库、多可用区、2 个同规格只读、2 TB 数据、每月 2 亿次读 I/O。

成本项自建兼容版(RDS 多可用区)共享存储版(Aurora)
主实例(按需,含多可用区双份)$700.80$350.40
只读副本 × 2$700.80$700.80
存储 2,000 GB$230.00(gp3)$200.00
I/O(2 亿次)含在存储里$40.00
备份(超出免费额度 1,000 GB)$95.00$95.00
合计(月)$1,726.60$1,291.20
合计(年)$20,719.20$15,494.40

两个结论:

  • 在这个配置下,共享存储版便宜约 25%(比值 1.34),主要来自多可用区不额外收一份计算费——它的高可用由存储层副本承担,不需要一个全职待命的备库。
  • 但这个比较对写入密集业务不成立:共享存储版的 I/O 按请求计费,写入量一大,第四行会迅速膨胀;而自建兼容版的存储单价是固定的。

口径:以上单价为 us-east-1 按需量级(2026 年口径),仅用于说明成本结构,不代表任何厂商报价;实际价格随区域、引擎版本、付费方式变化,请以官网价目页为准。换算成人民币时不要直接乘汇率做排名——跨境业务的真实成本还包括合规、带宽与人力。

10.2 四个隐藏项

隐藏项什么时候出现量级
跨地域复制流量开跨区只读副本或全球数据库每 GB 几分美元,日增 50 GB 的库每月约 1.5 TB
备份超出额度自动备份保留期拉长、快照长期保留与数据量同阶,长期快照能超过实例费
日志与监控慢日志、审计日志投递到日志服务按写入量计费,审计全开时不可忽略
I/O 请求共享存储版 + 高频小写入每月上亿次后成为主要成本项

10.3 省钱的正确顺序

  1. 关掉闲置副本:很多团队挂着 3 个只读副本,实际只有一个在承接流量。看连接数与 QPS 就能确认。
  2. 右规格化:连续两周 CPU 峰值低于 20%、内存低于 40% 的实例,降一档规格通常无损。
  3. 预留 / 节省计划:长期稳定的主库用 1 年期预留,折扣通常在三成量级;波动部分留给按需。
  4. 存储分层与归档:把两年前的冷数据迁走,既省存储也省备份。
  5. 最后才考虑换引擎族:迁移成本通常吃掉两到三年的差价。

十一、IaC:三云 RDS 的最小骨架

跨云架构最忌讳「控制台点出来的配置」。三家的实例参数含义不同,只有落到代码里才能做 code review、才能复现、才能在新区域快速克隆。


// AWS RDS MySQL:多可用区 + gp3 + 删除保护
resource "aws_db_instance" "orders" {
  identifier              = "orders-prod"
  engine                  = "mysql"
  engine_version          = "8.0"
  instance_class          = "db.r6g.xlarge"
  allocated_storage       = 2000
  max_allocated_storage   = 4000
  storage_type            = "gp3"
  multi_az                = true
  backup_retention_period = 14
  backup_window           = "18:00-19:00"
  deletion_protection     = true
  performance_insights_enabled = true
  storage_encrypted       = true
}

// 阿里云 RDS MySQL:高可用版(主备跨可用区)
resource "alicloud_db_instance" "orders" {
  engine           = "MySQL"
  engine_version   = "8.0"
  instance_type    = "mysql.x4.xlarge.2c"
  instance_storage = "2000"
  category         = "HighAvailability"
  security_ips     = ["10.0.0.0/8"]
  instance_name    = "orders-prod"
}

// 腾讯云 TencentDB for MySQL:双节点 + 8.0
resource "tencentcloud_mysql_instance" "orders" {
  internet_service  = 0
  engine_version    = "8.0"
  charge_type       = "POSTPAID"
  mem_size          = 32000
  volume_size       = 2000
  instance_name     = "orders-prod"
  mysql_version     = "8.0"
  availability_zone = "ap-singapore-2"
  instance_type     = "CUSTOM"
  root_password     = var.mysql_root_password
}

四点评注:

  • 参数名以 provider 版本为准。三家 Terraform provider 的属性会随版本变化,把 Version 固定在 lock 文件里,别用「最新」。
  • 别把 multi_az 当成跨区容灾。它只解决单可用区故障,跨区要另建跨地域副本资源。
  • deletion_protection 必须开。托管数据库的一次误删,恢复成本远高于一台服务器。
  • 密码走变量 + 密钥管理,不要进代码仓库。三家都支持从 KMS / 密钥管理服务取值。

一个实践建议:把「实例定义」「只读副本定义」「参数模板」拆成三个模块。因为只读副本的数量是随业务变化的,而主实例的规格相对稳定——混在一个模块里,每次加副本都要 touch 主实例的 state。

十二、迁移与割接:五步与一张检查表

从自建或跨云迁移,真正花时间的不是搬数据,而是校验与回滚预案。

步骤做什么工具(示例)验收标准
1. 评估版本、字符集、SQL 方言、对象数量慢查询日志 Top 200 + EXPLAIN 对比每条 SQL 在新实例上执行计划可接受
2. 结构迁移表、索引、视图、存储过程、触发器mysqldump / 厂商 DTS 结构迁移对象数量与定义完全一致
3. 全量 + 增量全量拷贝 + binlog 实时追平DTS / DMS / 自建 CDC增量延迟稳定在秒级
4. 数据校验行数、关键列校验和、抽样比对pt-table-checksum / 厂商内置校验差异为 0 或已逐条解释
5. 割接与回滚停写、切域名、验证、观察DNS / 连接串 / 代理配置首笔写成功,错误率回基线

割接窗口的八项检查:

  1. 应用侧连接串与连接池上限已按新实例调整(最容易漏的一项)。
  2. 只读流量已切到新实例的只读地址,且延迟监控已就位。
  3. 定时任务、离线作业、报表系统全部在清单里(它们往往直连旧库)。
  4. 备份与 PITR 已在新实例上验证过一次真实恢复。
  5. 回滚路径明确,且回滚所需的旧库仍可写(不要提前下线)。
  6. 监控告警的阈值按新实例重新校准(CPU 基线不同)。
  7. 慢查询日志、审计日志已开启并接入日志平台。
  8. 有一个人专门盯错误率曲线,不做其他事。

第 1 项值得单独强调:迁移事故里有相当比例不是数据库的问题,而是某个服务还用着旧的连接池大小,新实例的连接上限更低,于是一上线就打满。

十三、排障清单:按现象定位,而不是按经验猜

数据库故障的表象高度相似,根因却分布在不同层。下面这张表按「你看到的现象」组织,第一列就是值班时最该先看的判据。

现象第一判据常见根因下一步
CPU 100%,QPS 没涨慢查询数、活跃连接数缺索引、执行计划退化、统计信息过期抓 Top SQL,EXPLAIN 对比
QPS 下降,CPU 不高连接数、锁等待连接池打满、行锁排队、代理层限流看 PROCESSLIST 的 State 分布
只读查询报错或结果旧复制延迟、Seconds_Behind_Source大事务、DDL、备库规格不足查 worker 回放进度
写入突然变慢,偶发超时磁盘 IOPS、突发积分余额gp3 积分耗尽、存储打满看 CloudWatch / 监控的 BurstBalance
主备切换后应用不恢复DNS TTL、连接池旧连接重连段未处理缩短 TTL、开 keepalive
连接数缓慢上涨按来源 IP 聚合的空闲连接连接泄漏、maxLifetime 未设查 Sleep 连接归属
内存持续上涨后 OOMbuffer pool 外的会话缓冲sort_buffer / join_buffer 过大 × 高并发降会话缓冲、限并发
凌晨固定时间抖动备份窗口、批处理任务自动备份抢占 I/O、定时任务全表扫描错峰,或换低峰窗口
单表写入越来越慢索引数量、二级索引写放大索引过多、主键非递增精简索引,改用递增主键
跨可用区延迟升高应用与数据库的 AZ 分布跨 AZ 调用、跨区读写应用与主库同 AZ
账单突然翻倍存储增长、I/O 请求数、副本数数据未归档、日志全开按 10.2 的四个隐藏项核对
迁移后偶发重复数据唯一索引与排序规则排序规则不一致导致判重失效对比两端 collation

排障的第一原则是先分层再定位:连接层(能否连上)→ 执行层(SQL 是否变慢)→ 存储层(I/O 是否饱和)→ 复制层(备库是否追平)。跳过任何一层都会导致误判,最常见的误判是把「连接池打满」当成「数据库性能不足」,于是加规格,问题依旧。

十四、90 天落地路线

阶段时间交付物验收标准
现状盘点第 1–2 周实例清单、规格、峰值指标、慢查询 Top 100每个实例都有明确的业务归属人
基线压测第 3–4 周各引擎族的拐点曲线、复制延迟曲线知道单实例的上限在哪
高可用补齐第 5–6 周多可用区 / 三节点选型、切换演练报告演练 RTO 与错误率恢复时间有记录
读写分离第 7–8 周只读地址、会话粘滞策略、一致性级别读流量占比与主库压力下降可量化
连接层治理第 9 周代理或连接池统一配置弹性伸缩时连接数不再打满
成本优化第 10 周右规格化清单、预留采购建议月度账单下降且有据可查
分片评估第 11–12 周分片必要性结论(做或不做,都要有数据)用 6.2 的判据表逐项打勾

这张表里最重要的是最后一行:「不做分片」也是一个需要数据支撑的结论。没有评估就上线,等于把架构风险留给半年后的自己。

十五、总结

关系型数据库的多云架构,说到底只有四个变量:引擎族决定天花板,拓扑决定故障形态,扩展方式决定复杂度,连接模型决定稳定性。四个变量里,前两个花钱能解决,后两个只能靠设计。

三条最值得记住的判断:

  • 半同步不等于 RPO=0。超时退化是静默的,要监控退化事件而不是开关状态。
  • 只读副本的语义在三族里不同。共享存储版的副本共享数据、只回放日志;自建兼容版的副本异步复制 binlog。把两者的延迟预期互换,是跨云架构里最常见的错。
  • RTO 的重连段通常比切换段更贵。优化应用侧的重连与 DNS,往往比升级数据库拓扑更划算。

最后一句话:数据库是整套架构里迁移成本最高、回滚成本最高的组件。宁可多花两周做压测、切换演练和分片必要性评估,也不要在业务翻倍时被迫做一次全量重构。

🚀 企业出海需要云架构咨询?通过 7.chengzicloud.cloud 联系我们,获取专属方案。覆盖多云数据库选型、高可用与容灾设计、迁移割接与成本优化。

相关阅读

本文由 7.chengzicloud.cloud 提供,点击访问首页了解更多

常见问题(FAQ)

Q1:中小团队有必要一开始就上多可用区吗?

如果是生产库,有必要。多可用区把「单可用区故障」从一次几小时的事故,压缩成一次几十秒的切换,成本大约是单实例的两倍。对一年营收远高于这个差价的业务,它是最便宜的保险。只有内部工具、可重建的测试库,才适合单实例 + 快照。

Q2:共享存储版(Aurora / PolarDB / TDSQL-C)是不是一定比自建兼容版好?

不是。它的优势在读扩展快、副本延迟低、故障切换快、不用为高可用付第二份计算费;劣势在写入仍然单节点、I/O 按请求计费导致写入密集场景成本不可预测、以及部分运维细节(参数、插件、内核版本)与标准 MySQL 有差异。读多写少的业务收益明显,写入极高且小事务密集的业务反而可能更贵。

Q3:开了半同步复制,是不是就一定 RPO=0?

不是。半同步在等待超时后会退化为异步,而退化通常是静默的。MySQL 的默认超时是 10 秒,这意味着备库抖动超过 10 秒的那段时间里,主库已在接受「没有副本确认」的写入。要做到 RPO=0,需要多数派提交(三节点 / 强同步)或组复制,并且监控退化事件。

Q4:只读副本越多,读性能就越好吗?

通常会变差。副本多了,写入的 binlog 分发压力、跨区流量、监控与管理成本都上升,而每个副本的命中率并不会因为多一个副本而提高。正确的顺序是:先加缓存、再把检索类查询移到搜索引擎、最后才加只读副本。加副本前先确认读流量里有多少是可以被缓存掉的。

Q5:什么时候必须分库分表?

用 6.2 的判据表判断,比较硬的信号是:单表行数进入亿级、单库存储超过 2–4 TB、写入 QPS 长期超过单实例上限的 60%、单表 DDL 需要停机窗口。注意「行数」不是唯一信号,一张大表但只按主键查,往往比一张小表但写入频繁更健康。

Q6:分片键选错了还能救吗?

能,但代价很高。补救手段有三种:加一层映射表(把查询键翻译成实际分片)、做数据重分布(停机或双写迁移)、或者改成分布式数据库让中间件接管路由。第三种最省事但会绑定厂商。所以分片键要在设计阶段用「未来的查询模式」验证,而不是只按当前 SQL 验证。

Q7:跨云双活双写值得做吗?

对数据库这一层,绝大多数业务不值得。双写要解决冲突检测、自增冲突、跨云事务和锁持有时间放大四个问题,任何一个都可能吃掉收益。更务实的是「单写多读 + 明确的切换决策点」:写只落一个云,另一个云提供读与灾备接管,切换是单向且有预案的。

Q8:迁移后应用连不上,最先查什么?

按顺序查三件事:安全组 / 白名单是否放行了应用所在网段(跨云时最容易漏)、实例的连接数上限是否低于应用连接池总和、以及 DNS 是否已生效(TTL 未过期会连到旧实例)。这三项覆盖了迁移后连接问题的绝大部分。

Q9:为什么压测时性能很好,上线三天就变慢?

通常是三个原因之一:压测数据量小于内存,缓存全命中;存储的突发积分(如 gp3 的 BurstBalance)在持续负载下耗尽,IOPS 掉回基准值;或者真实流量的分布有热点,压测的均匀分布测不出热点行锁。对应解法是加大压测数据量、盯住突发积分、用真实流量回放做一次验证。

Q10:预留实例 / 节省计划能省多少,值得买吗?

长期稳定的主库通常能省三成左右的按需费用,一年期、全预付折扣最大。判断是否值得买的依据是「这个实例未来 12 个月会不会被降规格或迁移」——如果半年内要做架构调整,买了预留反而被锁住。稳妥做法是先右规格化,再对稳定部分买预留。

Q11:本文这套方法跟 10-02 单元化、10-21 多租户怎么配合?

顺序是:先定单元与租户边界(10-02、10-21),再按边界决定每个单元用哪种数据库拓扑(本文),最后才是缓存(10-09)与备份(09-11)。反过来先选数据库产品再想边界,通常会在租户数上来之后被迫做一次数据搬迁。

Q12:三云的托管数据库,能不能用同一套监控?

指标名不同,但语义可以对齐。建议统一采集五类指标:连接数、QPS/TPS、P99 延迟、复制延迟、存储与 IOPS 使用率。把这五项映射到同一套看板与告警规则上,跨云切换时运维习惯不用重学。用各家的 API 或 Prometheus exporter 都能做到,成本不高但收益长期。