分库分表是应对单库压力的务实方案,核心在于合理拆分(垂直/水平)与保障数据一致,需兼顾分片键设计、分布式事务处理及ID生成、分页、迁移等配套问题。

分库分表不是为了炫技,而是当单库扛不住数据量和并发压力时的务实选择。真正落地时,核心就两件事:怎么拆、拆完怎么保证数据一致。
垂直拆分:按业务边界切开,先解耦再减压
适合模块清晰、读写集中在各自领域的系统,比如电商里的用户、订单、商品三个模块。把 user 表全放 user_db,order 表全放 order_db,彼此独立部署、独立扩容。这种拆法改动小、风险低,还能天然隔离故障——订单库慢了不影响登录。
注意点:
- 跨库关联查不能用 JOIN,得靠应用层调接口组装,或者冗余关键字段(比如订单表里存用户昵称)
- 如果某业务突然爆发(如秒杀),单库仍可能成为瓶颈,这时需在该库内进一步水平分表
- 微服务架构下,垂直分库几乎是标配,它为后续服务自治打下基础
水平分片:按数据特征打散,专治大表和高并发
单表超 500 万行或写入 QPS 持续过千,就得考虑水平分片。常见做法是选一个稳定、分布均匀的字段作分片键,比如 user_id % 16 或 order_time 的年月,把数据分散到多个库+多张同构表中。
典型结构示例:
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
- db_order_0 里有 order_00、order_01 … order_07
- db_order_1 里有 order_08、order_09 … order_15
- 查 user_id=12345 的订单 → 算出落在 order_05 表,再路由到 db_order_0 库
关键提醒:
- 分片键一旦选定很难改,要兼顾查询高频条件、避免热点(如用“时间”做键易导致新数据扎堆)
- 非分片键查询(如按手机号查订单)必须建二级索引或映射表,否则要扫所有分片
- 分页、排序、COUNT、GROUP BY 这类聚合操作,需要中间件(如 ShardingSphere)合并结果,性能损耗明显
分布式事务:不强求 ACID,但要守住业务底线
跨库更新天然不支持本地事务,硬上两阶段提交(2PC)性能差、可用性低,实际项目中更常用三种思路:
- 避开跨库:设计阶段就约束,比如“下单”只写订单库,“扣库存”由商品服务异步处理,用消息通知驱动
- 最终一致性:用消息队列(如 RocketMQ 事务消息)发变更事件,下游消费后重试更新,适合对实时性要求不高的场景(如积分到账、通知推送)
- TCC 或 Seata AT 模式:需要强一致的关键链路(如支付成功+冻结资金),用 TCC(Try-Confirm-Cancel)或 Seata 的代理机制协调多个库,代价是开发成本高、需改造业务逻辑
绕不开的配套问题:ID、运维与查询
分库分表后,很多原来顺手的功能都得重做:
- 主键不能自增:推荐 Snowflake 算法生成 64 位全局唯一 ID,兼顾趋势递增和无中心依赖
- 跨库分页慢:避免 OFFSET LIMIT,改用“游标分页”(记录上次查询的最大 ID,下次查 WHERE id > ? LIMIT N)
- 数据迁移难:上线前用双写过渡(新老库同时写),再通过校验脚本比对一致性,确认无误后再切读流量
- 运维变重:备份要遍历所有分片,扩容需重新分片+迁移数据,建议用 ShardingSphere Proxy 或 MyCAT 降低应用侵入性








