分库分表前须先确认数据库确为瓶颈,通过SHOW PROCESSLIST、慢日志、iostat等定位锁等待、IO饱和或连接打满问题;仅当单实例CPU、内存、IO、连接数均持续超阈值且SQL优化无效时才考虑拆分。

分库分表前先确认瓶颈真在数据库
很多团队一遇到慢查询或连接数飙升,就急着上分库分表,结果发现是 SELECT * FROM order WHERE user_id = ? 缺少索引,或者事务里混了 HTTP 调用。先用 SHOW PROCESSLIST 和慢日志定位真实瓶颈:是锁等待(Locked 状态多)、还是 IO 饱和(iostat -x 1 中 %util 持续 100%)、抑或是连接打满(Threads_connected 接近 max_connections)。只有当单实例的 CPU、内存、IO、连接数四项都持续超阈值,且优化 SQL 和索引收效甚微时,才考虑架构层拆分。
读写分离要配好主从延迟监控和路由策略
MySQL 主从复制是异步的,Seconds_Behind_Master 可能突增到几十秒。如果所有读请求无差别发到从库,用户刚下单就查不到新订单,体验直接崩。必须做两件事:
– 对强一致性读(如订单详情、账户余额),强制走主库,可通过注释标记:/*FORCE_MASTER*/ SELECT balance FROM account WHERE id = 123;
– 对普通读,加延迟阈值判断:当从库延迟 > 500ms 时自动切回主库,不能只靠心跳检测;
– 应用层路由不能只看机器 IP,得结合 SHOW SLAVE STATUS 的实时延迟值动态决策,否则扩容从库后反而放大不一致风险。
水平分片别碰「全局自增 ID」这个坑
用 AUTO_INCREMENT 做分表主键,在跨分片 JOIN 或范围查询时会彻底失效,而且无法保证全局唯一。正确做法是:
– 用雪花算法(Snowflake)或 REPLACE INTO ... SELECT LAST_INSERT_ID() 类方案生成分布式 ID;
– 分片键必须是高频查询条件,比如电商系统优先选 user_id 而非 order_id,否则查订单号得扫所有分片;
– 单表数据量控制在 500 万行以内,但不要机械按时间切(如每月一张表),因为冷热数据混存会导致缓存命中率骤降;
– 所有分片必须统一字符集(utf8mb4)和排序规则(utf8mb4_0900_as_cs),否则跨片 UNION 时隐式转换引发全表扫描。
eSiteGroup站群管理系统是基于eFramework低代码开发平台构建,是一款高度灵活、可扩展的智能化站群管理解决方案,全面支持SQL Server、SQLite、MySQL、Oracle等主流数据库,适配企业级高并发、轻量级本地化、云端分布式等多种部署场景。通过可视化建模与模块化设计,系统可实现多站点的快速搭建、跨平台协同管理及数据智能分析,满足政府、企业、教育机构等组织对多站点统一管控的
连接池配置比 SQL 优化更能扛住突发流量
高并发下最常被忽视的是连接池参数。MySQL 默认 wait_timeout = 28800(8 小时),但应用层连接池若设 maxIdleTime=30000(30 秒),就会频繁创建销毁连接,触发 Too many connections。关键参数要对齐:
– 连接池最大连接数 ≤ MySQL 的 max_connections × 0.7(留 buffer 给 DBA 诊断);
– minIdle 设为 10~20,避免低峰期全释放;
– 启用 testOnBorrow 并配 validationQuery=SELECT 1,防止拿到底层已断开的连接;
– 如果用 HikariCP,务必关掉 leakDetectionThreshold 的默认值(0 表示关闭),线上开启会吃掉 10%+ CPU。
真正难的不是怎么分库,而是分完之后如何让开发写出不跨片的 SQL、如何让 DBA 快速定位某条记录在哪个分片、以及怎么在不停服前提下迁移存量数据——这些细节没配套机制,分库分表只会变成技术债加速器。









