数据库管理最热问答集锦,看完不再困惑 - 编号37858
去年某电商平台大促期间,数据库因连接池配置不当导致雪崩,最终损失超 2000 万元——而这本可以通过一个简单的 max_connections 参数调整避免。以下是开发者和 DBA 最常被问到的数据库管理痛点,每个问题都对应一个真实踩坑场景。
为什么索引建了,查询还是慢?——索引失效的 3 种隐藏场景
一位 SaaS 公司的后端工程师曾抱怨,给用户表的 email 字段加了唯一索引,但执行 SELECT * FROM users WHERE email LIKE '%@gmail.com' 时仍然全表扫描。问题出在:LIKE 以通配符开头时,B+树索引无法定位起始位置。同样,对索引字段使用函数(如 WHERE DATE(create_time) = '2024-01-01')也会让优化器放弃索引。最隐蔽的是隐式类型转换——当字段 varchar 类型传数字 123 时,MySQL 会全量转类型再比较,索引直接失效。
主从延迟导致数据不一致,加缓存能解决吗?
某金融交易系统的核心场景:用户提交订单后立刻查询订单状态,由于主库写入后从库尚未同步,读到的永远是旧数据。直接用缓存兜底反而更糟——缓存中存的是从库的“未更新数据”,造成用户反复看到提交前的页面。正确的做法是“强制读主库”:对订单这类写后即读的数据,在业务层通过路由将查询请求打到主库,或用 Redis 记录“刚写入的主键列表”,30 秒内匹配到该列表的查询走主库。另一个实战技巧是开启 MySQL 的 semi-sync 复制,确保从库至少有一台收到 binlog 后才返回给客户端成功。
表数据量过亿,分库分表后跨节点查询怎么优化?
某物联网平台存储设备上报数据,单表 3 亿行,按 device_id 分 32 个分片。结果业务方要查“某个时间段内所有设备的上报总数”,SQL 必须广播到所有分片再合并,一次查询耗时 15 秒。优化方案不是堆硬件,而是建立“汇总表”:在分库之外单独建一张分钟粒度的聚合表,由定时任务从各分片拉取增量数据合并写入。对于必须跨分片的分页查询,不要用 OFFSET + LIMIT,改用“游标分页”——每页返回一个 last_id,下次查询从该 ID 之后取 N 条,避免全分片排序。
避坑建议:
- 不要迷信“加索引万能”:组合索引要遵循“最左前缀原则”,且避免在索引列上做运算;每隔 3 个月用 EXPLAIN 检查慢查询,优先消灭 type=ALL 的扫描。
- 主从架构下,写后必读的操作必须强制路由到主库:不要指望从库“秒级同步”,业务层加一个 200ms 的延迟容忍逻辑,比加缓存更安全。
- 分库分表前先考虑分区表或冷热分离:70% 的场景根本不需要拆库,用 MySQL 的 RANGE 分区把历史数据归档到慢盘,活跃数据留在 SSD,成本低且管理简单。