📖 本篇简介:单表数据量从百万涨到千万、再涨到亿级,MySQL 的行为会发生质变——原本 10ms 的查询变成 10 秒,原本不心疼的一次 DELETE 变成 30 分钟主从延迟。本章汇总大数据量场景下最容易踩的 11 个坑,覆盖深分页、COUNT、JOIN、DDL、空间回收、binlog、冷数据归档、热点行、批量导入等典型问题。所有 SQL 示例基于 MySQL 8.0 语法。读完你能在数据量上涨之前就把方案准备好,而不是等库被打挂才救火。
本章适合已经经历过"表从百万涨到千万"阵痛的工程师,建议配合第 17 章(分库分表)、第 24 章(亿级表设计与迁移)、第 66 章(磁盘与容量)一起阅读。
数据量上涨时,最先出问题的往往不是"数据库扛不住",而是"那些数据量小的时候写得很爽、没人 review 的 SQL"。本章 11 个坑,每一个都是小数据量时写起来毫无问题、千万级就立刻爆炸的典型。
目录
- 坑 1:一次性 SELECT 全表不分页
- 坑 2:深分页 LIMIT 100000020 越翻越慢
- 坑 3:大表实时 COUNT 做总数
- 坑 4:大表 JOIN 小表顺序写反
- 坑 5:大表加索引走了 COPY 算法
- 坑 6:大表 DELETE 后不回收磁盘空间
- 坑 7:非覆盖索引回表拖慢大查询
- 坑 8:binlog 占满磁盘主库宕机
- 坑 9:冷数据不归档,热表无限膨胀
- 坑 10:高并发下热点行更新锁竞争
- 坑 11:批量导入一次提交锁表
- 常见注意事项:数据量上涨的预警信号
- 常用工具清单
- 速查表:大数据量红线一览
- 容量规划的简单算法
- 一句话总结
- 自测:数据量上来你怎么办
坑 1:一次性 SELECT 全表不分页
场景 / 错误示范:
-- 运营后台要"导出全部订单",开发直接跑
SELECT * FROM orders WHERE created_at >= '2024-01-01';
-- 错误:结果集 800 万行,应用 OOM,数据库网络打满
为什么是坑:MySQL 服务端会把结果集一行行通过网络推给客户端,客户端内存吃不下就 OOM;期间持有的会话、排序缓冲区、临时表都会占用资源。800 万行的导出不是一条 SQL 能解决的,必须分页或流式。
正确做法:
-- 正确 1:按主键游标分页,每次取 1000 条
SELECT * FROM orders
WHERE created_at >= '2024-01-01'
AND id > #{last_max_id} -- 上一批最大 id
ORDER BY id
LIMIT 1000;
-- 应用循环取,直到返回空
-- 正确 2:用 mysqldump 或 INTO OUTFILE 在数据库端直接导出
SELECT * FROM orders
WHERE created_at >= '2024-01-01'
INTO OUTFILE '/tmp/orders.csv';
加分点:流式导出要用服务端游标(如 pymysql 的 SSCursor),不要用普通客户端缓冲;导出任务必须限流,不能与在线业务抢 IO。
坑 2:深分页 LIMIT 1000000,20 越翻越慢
场景 / 错误示范:
-- 后台翻到第 5 万页
SELECT * FROM orders
WHERE user_id = 10086
ORDER BY created_at DESC
LIMIT 1000000, 20;
-- 错误:MySQL 要扫描前 1000020 行再丢弃前 100 万行,越翻越慢
为什么是坑:LIMIT offset, size 的执行逻辑是"扫描 offset+size 行,只返回最后 size 行"。offset 越大,丢弃的行越多,扫描成本线性增长。后台翻页到几千页后,单条查询就要几秒,用户越翻越卡。
正确做法:
-- 正确:游标分页(seek pagination),记住上一页最后一条的位置
-- 第一页
SELECT * FROM orders WHERE user_id = 10086
ORDER BY created_at DESC, id DESC
LIMIT 20;
-- 第二页:用上一页最后一行的 (created_at, id) 作为起点
SELECT * FROM orders
WHERE user_id = 10086
AND (created_at, id) < ('2026-10-01 12:00:00', 987654)
ORDER BY created_at DESC, id DESC
LIMIT 20;
加分点:后台系统不要让用户"跳页"到 100 万之后,业务上限制最多翻 100 页,超过就引导用户加筛选条件。
坑 3:大表实时 COUNT 做总数
场景 / 错误示范:
-- 商品列表页右下角显示"共 1234567 条"
SELECT COUNT(*) FROM product WHERE status = 1;
-- 错误:InnoDB 没有"行数"的全局计数器,要扫描索引或主键,千万级表就是秒级
为什么是坑:InnoDB 因为 MVCC,每个事务看到的行数不一样,无法维护一个全局准确的 COUNT。COUNT(*) 必须扫一遍索引,大表上是慢查询。列表页每次刷新都跑一次,数据库 CPU 被白白消耗。
正确做法:
-- 正确 1:近似值 / 缓存值,用 Redis 计数器
-- 商品上架/下架时维护 Redis 计数器,列表页直接读 Redis
-- 允许偏差几百条,业务上完全可接受
-- 正确 2:用 EXPLAIN 估算行数
EXPLAIN SELECT * FROM product WHERE status = 1;
-- EXPLAIN 输出的 rows 列是优化器估算值,不精确但很快
-- 正确 3:show table status 取粗略值
SHOW TABLE STATUS LIKE 'product';
加分点:只有 MyISAM 能瞬时返回精确 COUNT(*),但它不支持事务和行锁,生产环境不要为了 COUNT 切引擎。
坑 4:大表 JOIN 小表顺序写反
场景 / 错误示范:
-- order_item 有 1 亿行,product 有 100 万行
-- 开发写的 SQL:先从 product 全表扫,再 JOIN order_item
SELECT o.order_no, p.name
FROM product p
JOIN order_item o ON o.product_id = p.id
WHERE p.category_id = 5;
-- 错误:优化器虽然会优化,但如果统计信息过期,可能真按这个顺序执行
为什么是坑:JOIN 的驱动表选择直接决定扫描行数。小表驱动大表时,外层循环 100 万次、每次用索引探针大表;顺序反过来就是外层 1 亿次,性能差几个数量级。统计信息过期、索引缺失时,优化器可能选错。
正确做法:
-- 正确 1:永远用小结果集驱动大表
-- 先把 category_id=5 的 product 筛出来(可能只有几千条),再 JOIN order_item
SELECT o.order_no, p.name
FROM (
SELECT id, name FROM product WHERE category_id = 5
) p
JOIN order_item o ON o.product_id = p.id;
-- 正确 2:EXPLAIN 确认驱动表
EXPLAIN SELECT ...;
-- 看 id=1 的第一行是谁,type=ALL 的那行就是被全表扫的驱动表
加分点:STRAIGHT_JOIN 可以强制 JOIN 顺序,但这是最后手段;优先保证统计信息新(ANALYZE TABLE)、索引齐全。
坑 5:大表加索引走了 COPY 算法
场景 / 错误示范:
-- 5000 万行的订单表,要给 user_id 加索引
ALTER TABLE orders ADD INDEX idx_user (user_id);
-- 错误:以为 8.0 默认 ONLINE,结果因为某些配置走到了 COPY,锁表 40 分钟
为什么是坑:8.0 虽然默认 INPLACE,但加全文索引、空间索引、改列类型等场景仍可能 COPY;更隐蔽的是 metadata lock——如果有长事务持有表的 MDL,ALTER 会排队,后续所有读写都被阻塞。
正确做法:
-- 正确 1:显式声明算法,让 MySQL 校验
ALTER TABLE orders ADD INDEX idx_user (user_id),
ALGORITHM=INPLACE, LOCK=NONE;
-- 如果实际必须 COPY,语句直接报错,提前暴露风险
-- 正确 2:大表用 gh-ost / pt-online-schema-change
-- 这些工具通过 binlog 增量同步 + 影子表切换,业务无感知
-- 正确 3:先杀长事务,再执行 DDL
SELECT * FROM information_schema.innodb_trx
WHERE trx_starttime < NOW() - INTERVAL 1 HOUR;
加分点:DDL 必须在业务低峰执行,并且先在从库上跑一遍观察时长;执行期间盯紧 SHOW PROCESSLIST,一旦看到 Waiting for table metadata lock 立刻 kill。
坑 6:大表 DELETE 后不回收磁盘空间
场景 / 错误示范:
-- 删了 8000 万行历史日志,预期磁盘释放
DELETE FROM browse_log WHERE created_at < '2024-01-01';
-- 观察:磁盘使用率一点没降!
为什么是坑:InnoDB 的 DELETE 只是把记录标记为删除,空间留在表空间里供后续 INSERT 复用,并不会还给操作系统。共享表空间(ibdata1)甚至只增不减。长期下来磁盘被"死数据"占满。更隐蔽的是,标记删除的记录还会占在数据页里,扫描时仍然要遍历到,性能并不会立刻好转。
正确做法:
-- 正确 1:重建表回收空间(大表要低峰 + pt-osc)
ALTER TABLE browse_log ENGINE=InnoDB; -- 重建,物理收缩
-- 正确 2:更彻底——分区表,DROP 分区瞬间回收
ALTER TABLE browse_log DROP PARTITION p2023q4;
-- 正确 3:大表用独立表空间
SET GLOBAL innodb_file_per_table = ON; -- 8.0 默认开启
加分点:数据清理优先用"分区 + DROP 分区",比 DELETE 快几个数量级,而且不产生大量 undo/redo;按月份做 RANGE 分区是日志类表的标配。
坑 7:非覆盖索引回表拖慢大查询
场景 / 错误示范:
-- 索引建在 (user_id, status)
SELECT * FROM orders
WHERE user_id = 10086 AND status = 1;
-- 错误:走了二级索引,但 SELECT * 要回表取所有列
-- 这个用户有 5 万条订单,就回表 5 万次,随机 IO 爆炸
为什么是坑:二级索引叶子节点只存索引列 + 主键,要取其他列必须拿主键回聚簇索引查一次。回表是随机 IO,数量一大就慢。MySQL 用"回表成本估算"决定走二级索引还是全表扫,估算偏差时就会走错。
正确做法:
-- 正确 1:把查询需要的列都建进索引,走覆盖索引
SELECT order_id, status, amount, created_at
FROM orders
WHERE user_id = 10086 AND status = 1;
-- 配套建联合索引
ALTER TABLE orders ADD INDEX idx_user_status_cover
(user_id, status, order_id, amount, created_at);
-- EXPLAIN 看到 Extra=Using index 就是覆盖索引,不回表
-- 正确 2:如果确实需要 SELECT *,就限制返回行数
SELECT * FROM orders WHERE user_id = 10086 AND status = 1 LIMIT 20;
加分点:覆盖索引不是越长越好,索引本身也占写入成本;按高频查询的列组合设计,不要为了一条 SQL 把索引建得比表还宽。
坑 8:binlog 占满磁盘主库宕机
场景 / 错误示范:
-- 运维只关注数据目录大小,没管 binlog 目录
-- 某天磁盘告警:/var/lib/mysql 已经 95%,全被 binlog.000123 这种文件占了
-- 查看:
SHOW VARIABLES LIKE 'expire_logs_days'; -- 老版本
SHOW VARIABLES LIKE 'binlog_expire_logs_seconds'; -- 8.0
-- 配置成了 0,binlog 永不删除
为什么是坑:binlog 是主从复制和 PITR 的依据,一旦主从复制延迟或从库挂了,主库不敢删 binlog;如果再配成永不过期,磁盘迟早被撑爆。磁盘满后 MySQL 无法写入,整库宕机。
正确做法:
-- 正确 1:设置 binlog 自动过期,生产一般 3~7 天
SET GLOBAL binlog_expire_logs_seconds = 604800; -- 7 天
-- 正确 2:手动清理已备份/已回放的 binlog
PURGE BINARY LOGS BEFORE '2026-10-01 00:00:00';
PURGE BINARY LOGS TO 'mysql-bin.000100';
-- 正确 3:监控磁盘,binlog 目录单独挂载
-- 告警阈值:使用率 > 70% 预警,> 85% 紧急
加分点:清理前先确认所有从库已经拉完这些 binlog,否则从库复制会断;SHOW REPLICA STATUS(8.0,老版本 SHOW SLAVE STATUS)看 Relay_Master_Log_File。
坑 9:冷数据不归档,热表无限膨胀
场景 / 错误示范:
-- 订单表从 2020 年积累到现在,8 亿行,全在一张表
-- 每次加索引要几小时,每次查询要扫几亿行
-- 实际上 95% 的查询只看最近 3 个月
为什么是坑:业务数据只会增长不会减少。冷数据(历史订单、已完结日志)占了 90% 空间,但查询量不到 5%,却让热数据的索引、缓冲池、备份都被拖慢。这是典型的"冷热不分"。
正确做法:
-- 正确 1:按时间分区,历史分区 DROP 或 detach
CREATE TABLE orders (
id BIGINT,
created_at DATETIME,
...
) PARTITION BY RANGE (TO_DAYS(created_at)) (
PARTITION p2024q1 VALUES LESS THAN (TO_DAYS('2024-04-01')),
PARTITION p2024q2 VALUES LESS THAN (TO_DAYS('2024-07-01')),
PARTITION p2024q3 VALUES LESS THAN (TO_DAYS('2024-10-01')),
PARTITION pmax VALUES LESS THAN MAXVALUE
);
-- 正确 2:更彻底——热库在 MySQL,冷库在 HBase / OSS / 数仓
-- 访问路径:先查热库,miss 再查冷库
加分点:归档策略要在业务上线第一天就设计好,等数据到亿级再补迁移,成本是一开始就分区的十倍。
坑 10:高并发下热点行更新锁竞争
场景 / 错误示范:
-- 秒杀:所有请求都扣同一个商品 id=100 的库存
UPDATE stock SET count = count - 1 WHERE sku_id = 100;
-- 错误:这一行变成热点,所有事务串行排队
-- QPS 1 万时,锁等待队列堆积,接口 P99 飙到秒级
为什么是坑:InnoDB 行锁是悲观锁,同一行的并发写必须串行。热点行(直播间商品、大 V 粉丝数、全局计数器)会成为系统瓶颈,再高的机器配置也扛不住单行 QPS。
正确做法:
-- 正确 1:热点拆分——把一个库存拆成 N 个分片
-- stock 表变成:(sku_id, bucket_id, count),bucket_id 0~9
-- 请求进来随机选一个 bucket 扣减,最终库存 = SUM(count)
UPDATE stock SET count = count - 1
WHERE sku_id = 100 AND bucket_id = FLOOR(RAND()*10);
-- 正确 2:用 Redis 预扣库存,异步落库
-- Redis DECR 扛万级 QPS,扣成功后发 MQ,消费者慢慢写 MySQL
加分点:热点问题的本质是"把一个key的并发变成 N 个 key 的并发",除了库存,计数器、点赞数、粉丝数都可以这么拆。
坑 11:批量导入一次提交锁表
场景 / 错误示范:
-- 数据迁移:把 1000 万行从老库导到新库
-- 脚本里开了一个大事务,一次性 INSERT 全部
BEGIN;
INSERT INTO new_orders VALUES (...), (...), ...; -- 1000 万行
COMMIT;
-- 期间 undo log 暴涨,主从延迟 1 小时,新库写入阻塞
为什么是坑:单事务越大,持锁时间越长、binlog 事件越大、主从回放越慢;一旦中途失败回滚,1000 万行的回滚又是一场灾难。批量导入必须小步提交,让主从复制和 purge 线程能跟上。
正确做法:
# Python 伪代码(本示例基于 MySQL 8.0),批量分批提交
BATCH = 1000
rows = load_from_old_db() # 老库读出来的 1000 万行
for i in range(0, len(rows), BATCH):
batch = rows[i:i+BATCH]
cur.executemany(
"INSERT INTO new_orders(id, amount) VALUES (%s, %s)",
batch
)
conn.commit() # 每 1000 行提交一次
time.sleep(0.05) # 给从库留喘息
加分点:批量导入期间临时关唯一索引检查、关 autocommit 可以提速;但务必在导入完成后恢复,并重新 ANALYZE TABLE 让优化器拿到新统计信息。
常见注意事项:数据量上涨的预警信号
| 预警信号 | 说明 | 处置时机 |
|---|---|---|
| 单表行数 > 500 万 | 还能扛,但要开始关注慢查询 | 开始设计索引与归档 |
| 单表行数 > 2000 万 | 加索引开始要分钟级 | 必须走在线 DDL 工具 |
| 单表行数 > 1 亿 | 索引维护成本陡增 | 考虑分区 / 分库分表 |
| 单表大小 > 50GB | 备份恢复时间变长 | 必须分库或归档冷数据 |
| 慢查询占比 > 5% | 索引或 SQL 出问题 | 立刻拉慢日志复盘 |
| 主从延迟 > 10s | 大事务或大查询打满 IO | 定位大事务并拆分 |
数据量上涨不是一夜之间的事,通常有几个月的窗口。关键是在窗口内就把方案做好,而不是等 P99 飙到 5 秒才动手。
-- 定期巡检:查看各表大小与行数(本示例基于 MySQL 8.0)
SELECT TABLE_SCHEMA, TABLE_NAME,
TABLE_ROWS,
ROUND(DATA_LENGTH/1024/1024/1024, 2) AS data_gb,
ROUND(INDEX_LENGTH/1024/1024/1024, 2) AS index_gb
FROM information_schema.TABLES
WHERE TABLE_SCHEMA NOT IN ('mysql','sys','information_schema','performance_schema')
ORDER BY DATA_LENGTH DESC
LIMIT 20;
常用工具清单
| 工具 | 用途 | 适用场景 |
|---|---|---|
| pt-online-schema-change | 在线 DDL | 大表加列加索引 |
| gh-ost | 在线 DDL,无触发器 | 对主库压力敏感 |
| mysqldump | 逻辑备份 | 中小表导出 |
| mydumper / myloader | 并行逻辑备份 | 大表并行导出导入 |
| pt-archiver | 数据归档 | 分批把冷数据搬到冷库 |
| Percona Toolkit | 慢查询分析、死锁日志 | 日常巡检 |
| sysbench | 压测 | 上线前评估容量 |
工具是手段,关键还是要知道"什么时候该上工具"。等问题发生再查工具怎么用,已经晚了。建议在项目早期就把这些工具的安装、权限、演练流程跑通一次,真出事时才不会手忙脚乱。
速查表:大数据量红线一览
| 场景 | 错误做法 | 正确做法 |
|---|---|---|
| 导出全表 | 一条 SELECT * 拉回应用 | 主键游标分页 / INTO OUTFILE |
| 深分页 | LIMIT 1000000,20 | 游标分页 (created_at,id) < (...) |
| 总数统计 | COUNT(*) 实时查 | Redis 计数器 / EXPLAIN 估算 |
| JOIN | 大表驱动小表 | 小结果集驱动,EXPLAIN 验证 |
| 加索引 | 直接 ALTER | ALGORITHM=INPLACE, LOCK=NONE + gh-ost |
| 删除历史 | DELETE 大批量 | 分区 DROP PARTITION |
| 回表 | SELECT * 走二级索引 | 覆盖索引 / LIMIT 限制 |
| binlog | 永不过期占满磁盘 | 7 天自动清理 + 磁盘监控 |
| 冷热数据 | 全塞一张表 | RANGE 分区 + 冷库归档 |
| 热点行 | 单行 UPDATE 秒杀 | 分桶拆 N 行 + Redis 预扣 |
| 批量导入 | 单事务 1000 万行 | 每 1000 行提交一次 |
| 覆盖索引 | SELECT * 走二级索引回表 | 高频查询列建联合索引 |
| 空间回收 | DELETE 后等 OS 自动回收 | DROP PARTITION / ALTER 重建 |
| 备份 | 全量备份每天一次 | 大表要考虑增量 + binlog 备份 |
容量规划的简单算法
做容量规划时,至少要回答三个问题:现在多大?每月涨多少?什么时候到瓶颈?下面这段 Python 伪代码可以作为每年一次的容量复盘脚本。
# 简单的容量预测(本示例基于 MySQL 8.0 的 information_schema)
# 假设当前 data_gb = 200,每月增长 15GB,磁盘上限 800GB
current_gb = 200
growth_per_month = 15
disk_limit_gb = 800
months_left = (disk_limit_gb * 0.7 - current_gb) / growth_per_month
print(f"按当前增速,{months_left:.1f} 个月后达到 70% 告警线")
# 输出:按当前增速,26.7 个月后达到 70% 告警线
不要等到磁盘 90% 才开始扩容。70% 是告警线,80% 是必须动手线。提前半年规划分库分表或归档,比临时买磁盘、临时做迁移从容得多。
一句话总结
大数据量场景的核心矛盾是:索引、缓冲池、备份、主从复制都是为"热数据"设计的,但冷数据会一直赖在热库里占资源。越早把冷热分离、分区、归档做掉,后面越轻松;等表到了亿级再补,每一个改动都是伤筋动骨的工程。
再补一句:数据量上涨是必然的,数据库本身不会突然"扛不住",扛不住的是那些在数据量小的时候写得太随意、又没有随数据量演进而重构的 SQL 与表结构。定期复盘慢查询、定期巡检大表、定期做容量规划,比临时抱佛脚有用得多。
自测:数据量上来你怎么办
题 1:LIMIT 1000000, 20 为什么慢?怎么优化?
<details>
<summary>参考答案</summary>
MySQL 要扫描 offset+size 行,只返回最后 size 行,offset 越大丢弃越多,成本线性增长。优化用游标分页:记住上一页最后一行的 (created_at, id),下一页用 WHERE (created_at, id) < (...) 直接定位,配合联合索引 (user_id, created_at, id),无论翻到第几页都是常数成本。
</details>
题 2:DELETE 删了 8000 万行为什么磁盘没释放?
<details>
<summary>参考答案</summary>
InnoDB 的 DELETE 只是标记删除,空间留在表空间供后续 INSERT 复用,不还给操作系统;共享表空间 ibdata1 只增不减。要真正回收:ALTER TABLE ... ENGINE=InnoDB 重建,或改用 RANGE 分区后 DROP PARTITION。后者对大表更友好,瞬间完成且不产生 undo。
</details>
题 3:大表上 COUNT(*) 为什么慢?怎么替代?
<details>
<summary>参考答案</summary>
InnoDB 因为 MVCC 无法维护全局准确行数,COUNT(*) 要扫索引。替代方案:Redis 计数器在业务写入时维护(允许偏差)、EXPLAIN 的 rows 列做粗略估算、SHOW TABLE STATUS 取近似值。不要为了精确 COUNT 把引擎切到 MyISAM。
</details>
题 4:秒杀扣库存热点行怎么解?
<details>
<summary>参考答案</summary>
单行 UPDATE 受 InnoDB 行锁限制,并发写必须串行。方案一:把一个库存拆成 N 个 bucket 行,请求随机选 bucket 扣减,最终库存 SUM;方案二:Redis 预扣扛万级 QPS,扣成功后发 MQ,消费者异步落 MySQL。本质都是把单行并发变成多行/多 key 并发。
</details>
题 5:大表 DDL 为什么要显式写 ALGORITHM=INPLACE, LOCK=NONE?
<details>
<summary>参考答案</summary>
显式声明后,MySQL 会校验本次 DDL 是否真的支持在线变更;如果实际必须 COPY 或必须锁表,语句直接报错而不是悄悄跑几十分钟锁死业务。再配合 gh-ost / pt-online-schema-change 工具,把对业务的影响降到秒级。
</details>
题 6:binlog 把磁盘占满了怎么办?
<details>
<summary>参考答案</summary>
先确认所有从库已经拉完待清理的 binlog(SHOW REPLICA STATUS 看 Exec_Master_Log_Pos),再用 PURGE BINARY LOGS TO 'mysql-bin.000xxx' 安全删除;长期方案是设置 binlog_expire_logs_seconds=604800(7 天)自动清理,并对 binlog 目录单独挂载磁盘 + 70% 告警。
</details>
题 7:冷热数据分离有哪几种做法?
<details>
<summary>参考答案</summary>
从轻到重:表内按时间 RANGE 分区,历史分区 DROP;按时间分表(order_2024q1、order_2024q2),冷库查历史月份;热库在 MySQL,冷库迁移到 HBase / OSS / 数仓,查询路径先热后冷。原则是"写路径只碰热数据,读路径按需穿透到冷库"。选型时要考虑团队的运维能力:分区最省事,分表要引入路由中间件,冷库要额外维护一套存储。
</details>
题 8:一条 SQL 跑了 30 秒把主库 CPU 打满,你怎么处理?
<details>
<summary>参考答案</summary>
第一步 SHOW PROCESSLIST 找到这条会话,必要时 KILL 止损;第二步拉慢日志看 EXPLAIN,确认是索引失效、还是 JOIN 顺序错、还是结果集过大;第三步改写 SQL 或加索引,先在从库上验证执行计划;第四步把这条 SQL 加入 SQL 审核平台,防止再次上线。整个过程要在 15 分钟内完成,否则业务持续受损。
</details>
下一篇预告:第 74 章 事故复盘:慢查询拖垮库
文章回复
0 条公开回复