Ruankao System Analyst (Senior) study materials
Ruankao System Analyst (Senior) study resources

计费详单库:分库分表之前该做什么

Ruankao System Analyst (Senior) · Put your knowledge to work in context.

All case studies

计费详单库:分库分表之前该做什么

某电信运营商计费详单库保存13个月在线数据,主表12亿行、约2.1TB,按日分区但历史分区从未清理,冷热数据混在同一张表,备份窗口已达6小时。日增详单2000万条,营业厅需按手机号码查询近13个月详单,当前平均响应8秒、超时率12%。现有索引为(号码,起始时间),但统计类SQL普遍带函数转换,导致索引失效。报表团队每日6次直连生产库执行聚合SQL,业务高峰期数据库CPU持续95%以上。架构为一主两从,binlog为ROW格式,高峰期从库延迟最高达90秒,部分前台查询已读到过期数据。曾尝试把报表迁到从库,因延迟被迫回退。运维尝试加索引后写入性能下降,大促期间出现过一次大事务导致的复制中断。管理层倾向直接分库分表,但客户明确要求查询界面与操作习惯不得改变,改造后详单查询P95不超过2秒,预算只够一轮改造,且改造期间系统不停机。系统还承担每月一次的监管数据报送,需按全省维度做全量统计,须在每月5日前完成。运维团队5人,无专职DBA,缺乏分库分表运维经验。

1. 判断当前瓶颈主要来自容量、索引还是访问模式,给出诊断步骤与判断依据,并说明为什么不应直接分库分表。

Read the worked answer

先取证后结论,四步诊断

  1. 看等待事件与执行计划:若8秒均值主要来自db file scattered read、全分区扫描或大量回表,则属于访问模式问题(分区裁剪失效、函数转换导致索引失效),而不是数据量问题。
  2. 看SQL来源分布:报表每日6次直连跑聚合,CPU 95%,这是典型的混合负载互相干扰,属于架构问题(OLTP与OLAP未隔离)。
  3. 量化容量因素:12亿行、2.1TB对B+树索引只增加2–3次IO,通常不足以解释8秒;只有当索引选择性差、回表次数多时才会放大。
  4. 看复制延迟:从库延迟90秒,说明存在大事务或全表更新;这也是“报表迁从库”失败的直接原因--换位置不解决负载形态。

结论:主要矛盾是访问模式+负载未隔离,容量是次要因素。此时直接分片,会把同一条慢SQL复制到每个分片,问题放大N倍,而且预算只有一轮改造,打光了就没有退路。

应先做的四件事(成本低、见效快):报表迁至独立只读库或数仓;按“号码+时间”建组合索引并改写带函数的谓词,强制分区裁剪;历史分区滚动归档到冷存储;把大事务拆批次,恢复并行复制。做完再评估是否仍需分片。

2. 若最终必须分库分表,说明分片键的选择理由、跨片查询与报表的处理方式,以及迁移步骤。

Read the worked answer

分片键选用户(号码哈希),不选时间。

理由:营业厅查询90%以上是“按号码查近13个月详单”,按用户分片可保证单分片命中;按时间分片会让热点全部压在最新分片,写放大且负载不均,而单用户跨月查询反而要扫多个分片,与主要访问路径相悖。

代价与应对

  • 跨片统计:按时间范围、按全省维度的聚合无法路由,改由CDC解析binlog同步到数仓,报表与监管报送走分析库;在线库只保留点查能力。
  • 非分片键查询(订单号、身份证):建映射表(订单号→用户ID),或用基因法把用户ID后缀嵌入订单号,避免全片扫描。
  • 历史数据:13个月以前迁至冷表/对象存储,由统一查询网关路由,前端界面与操作习惯保持不变--这是满足“界面不改”的关键,而不是靠分片本身。
  • 扩容:预分64或128个逻辑分片,用范围映射或一致性哈希落到物理库,扩容按逻辑分片迁移,避免取模重分布导致全量搬迁。

迁移步骤:双写(写新库同时写旧库)→ 全量迁移 → 增量追平 → 数据比对(行数、金额汇总、抽样明细)→ 灰度切读 → 切写 → 观察期保留回滚开关。切写前比对不通过一律不切;全程不停机靠双写与灰度,而不是靠停机窗口。

3. 在主从延迟90秒的前提下,说明读写分离策略、缓存一致性处理以及应写入SLA的业务妥协。

Read the worked answer

一致性是业务属性,不是技术属性:先问“这条数据读错了会怎样”,再决定走主库还是从库。

  • 写后读:用户刚提交的变更必须走主库,或将“最近N秒被修改的键”打标强制路由主库(read-your-writes),保证本人看到自己的结果。
  • 按数据分类路由:余额、计费结果、当月账单走主库;历史详单列表、统计类走从库,并在界面标注“数据截止时间”。
  • 缓存:只缓存可容忍短暂陈旧的数据;更新策略用“先更新库、再删除缓存”,配合延迟双删或binlog订阅失效,避免脏数据长期滞留;对强一致字段不使用缓存读。
  • 延迟治理:排查大事务、开启并行复制、给从库减负(去掉报表SQL);设置延迟告警阈值(如>30秒告警、>60秒自动把读流量切回主库并限流)。
  • 写入SLA的业务妥协:明确“详单查询可能存在不超过1分钟延迟”“监管报送数据以T+1为准”。写在合同与界面提示里,比事后解释可控得多。

判断原则:读写分离解决的是吞吐,不解决正确性;只要业务无法接受陈旧读,就必须在主库侧或应用侧做补偿(如提交后返回版本号、读时校验版本),而不是假设从库“应该很快跟上”。