一条DELETE删千万行|从库延迟飙到八分钟

简介: 从一条 DELETE 删千万行、跑半小时没完、主从延迟飙到八分钟切入,拆清一条大 DELETE 其实是一个大事务:undo 只涨不缩、行锁持有到提交、ROW binlog 撑爆带宽、回滚比执行更久。给出按主键分批的脚本、批次监控与场景判断表,并说明能归档就别硬删。

大家好,我是数据库小学妹👋 我踩过的坑,你别再踩。

去年清历史订单,我写了一条 DELETE,圈了一千万行。我想着删数据嘛,减法,跑完就轻了。结果它跑了半个多小时还没完。先来的是慢查询告警。接着主从延迟飙到八分钟,磁盘占用也在往上涨。

我盯着监控有点懵。数据在减少,库怎么越来越重。后来把这条语句拆开看才明白。一条 DELETE 不是一次操作,是一千万次操作,而且全塞在同一个事务里。

删除这件事,不是减法

InnoDB 删一行,干的活比想象中多。它先把行标记成已删,再写一条 undo,记下这行原来长什么样。回滚要靠它,MVCC 也要靠它。同时写 redo,保证崩溃后能恢复。开了 ROW 格式的话,binlog 里还要记一份前镜像。

一行四笔账,一千万行就是四千万笔。磁盘上真正少掉的数据,要等后台 purge 线程慢慢清。而 purge 得等你这个事务结束。所以删得越多,先背上的东西越重。日志先落盘,数据页还没清。所以删除过程中,磁盘占用常是先涨后降。那天我看到磁盘往上走,就是这个原因。

undo:删得越多,背得越重

undo 是给回滚用的。事务不结束,它就不敢清。一千万行的 DELETE 跑半小时,这半小时里 undo 一直长,purge 一直追不上。用一条命令就能看这个水位。

SHOW ENGINE INNODB STATUS\G
-- TRANSACTIONS 段里的 History list length

这个数一直涨,就说明历史版本在堆积。undo 表空间跟着涨,而且只涨不缩。有活跃事务占着它,truncate 也做不了。磁盘告警常常不是数据造成的,是 undo 撑出来的。undo 涨太多,还有个隐性代价。别的查询走 MVCC 时,要顺着更长的版本链找可见版本。链越长,扫得越慢。你删的是历史数据,被拖慢的却是线上查询。

更麻烦的是回滚。真跑到一半你受不了,KILL 掉会话,InnoDB 得拿着 undo 一行一行翻回去。一千万行的回滚,可能比删还久。而且这期间它照样吃 IO,照样堵着锁。

锁:提交之前,谁都别碰

一条 DELETE 是一个事务,行锁要持有到提交才释放。删过的那些行,别的事务想改,只能等。要是条件字段没索引,问题更大。InnoDB 锁的是扫描到的索引记录。全表扫一遍再删,锁的范围会远超你想象的几行。RR 隔离级别下还有间隙锁,锁住的不只是行,还有行之间的空隙。我见过一条 DELETE,条件字段没索引,锁住的是一整段扫描区间。后面的 UPDATE 全在排队,等到超时,业务开始报错。所以大 DELETE 最难受的地方在锁的时间。它不只是一条语句慢,它让一批业务操作一起排队。

binlog:从库跟不上的那一段

ROW 格式下,每删一行,binlog 里就有一份前镜像。一千万行,体积很可观。主库写完还要传给从库,从库再一行行回放。主库删得快,从库追不上,延迟就出来了。那天飙到八分钟,业务读从库拿到的是旧数据。binlog 文件也在涨,备份体积跟着涨,CDC 那边也会被这波流量冲一下。写之前先记一下当前 binlog 大小,删完再比一次,涨了多少心里就有数。

SHOW BINARY LOGS;
SHOW REPLICA STATUS\G
-- 看 Seconds_Behind_Source 和 Relay_Log_Pos

那到底该怎么删

动手前先量三件事。要删多少行,现在主从延迟多少,磁盘还剩多少。行数可以用 EXPLAIN 估,别直接跑 COUNT(*)。顺手看一眼 binlog 保留策略,别删到一半把日志挤爆。

核心思路只有一句:把一个大事务拆成很多小事务。注意,总工作量没变,变的是锁、undo、binlog 分段释放。代价没有消失,只是被摊开了。分批不是让删除变快,是让它的影响能被控制。

维度 一条删完 按主键分批
锁持有 到提交才放 每批结束就放
undo 一直涨到提交 分段回收
binlog 一次性写满 分段产生
中途停止 回滚很慢 随时能停
主从延迟 冲得很高 可以控速

先按主键分批,别用 LIMIT 直接切,那样每次都要重新扫描定位。

-- 每批两千行,批间停半秒,直到影响行数为 0
DELETE FROM t_order
WHERE created_at < '2025-01-01'
ORDER BY id
LIMIT 2000;

跑完一批,SELECT ROW_COUNT() 看影响行数。大于零就歇一下再来。停多久看从库,延迟抬头就把 sleep 拉长,或者把批减小。批大小没有标准答案。我的经验是两千到五千行一批,先在从库上试。批太大单批就超过一秒,从库照样追不上。

更稳的是按主键区间走,连排序都省了。

DELETE FROM t_order
WHERE id > 8800000 AND id <= 8802000
  AND created_at < '2025-01-01';

跑的过程盯四个数。主从延迟、Threads_running、History list length、磁盘余量。哪个不对就停。停是安全的,分批本来就为了能停。不想自己写循环,pt-archiver 也能做。--limit 控批大小,--sleep 控间隔,--commit-each 保证每批提交。

哪些情况可以一条删完

不是所有删除都要分批。几万行、低峰、表不大,一条删完更省事。判断的关键是这条语句会造出多大的事务。先看它会摸到多少行,再看它要持锁多久。

场景 做法
几万行以内、低峰 一条 DELETE 可以
百万级、只删一部分 按主键分批,批间留间隔
整表清空 用 TRUNCATE,别一行行删
时间分区表、整段历史 先归档,再 DROP PARTITION
有 CDC、审计、同步链路 必须分批,盯 binlog 体积

整表清空这条特别值得说。很多人习惯 DELETE FROM t,删得慢,undo 和 binlog 还全记一遍。TRUNCATE 是重建表,快得多,日志也少。前提是这张表没有外键引用,也没人正拿着它的数据。

还有一类最容易被忽略。数据以后可能还要查,别急着删。先搬去归档表,对完账再删源数据。删错了还能回头,这才是稳。

避坑清单

别一条 DELETE 删百万级。你以为在省事,实际是在造一个超长事务。锁、undo、binlog 全跟着它一起膨胀。

分批别只加 LIMIT。没有排序或主键条件,每批都在重新扫表,越删越慢。按主键区间走,代价才是稳定的。

最后一条是我自己踩的。那次千万行 DELETE 跑不动,我直接 KILL,想着停下来就没事了。结果回滚比删还久,从库延迟反而更高。从那以后我记住,删得慢还能停,回滚开始就停不了了。现在大删除一律先分批,压根不给回滚机会。

写在最后

删除在业务眼里是减法。在 InnoDB 里,它先是一笔账。undo 记着,binlog 记着,锁压着,从库追着。行,到后面才真的消失。

所以大表删除这道题,考的不是 SQL 写得对不对。考的是你会不会把一个巨大事务拆开。拆成能停、能看、能收手的节奏。数据可以分批走。代价不能一笔勾销。

你们清理历史数据,是一次删完还是分批?有没有被回滚坑过?评论区聊聊。

我是数据库小学妹,帮你少走弯路少踩坑,咱们下篇见👋

相关文章
|
云安全 安全 网络安全
|
6天前
|
JavaScript 安全 前端开发
Nodejs Brotli decoder 代码执行漏洞 (CVE-2026-111497)10629
Node.js发布安全更新修复Brotli解码器高危RCE漏洞(CVE-2026-111497),建议受影响版本用户立即升级。
1987 1
|
13天前
|
人工智能 API 开发工具
DeepSeek Harness 神插件:白嫖 13 家大厂模型
`dsh-our-free-model` 是 DeepSeek Harness 神级插件:零配置、零API Key、零账号,聚合13家大厂免费模型(含DeepSeek V4.1 Flash、Kimi K3等),支持本地网关、用量看板与自动降级,真正实现“白嫖即用”。
2143 43
|
10天前
|
Web App开发 人工智能 前端开发
2026 年 AI 浏览器怎么选?Ego Lite、Tabbit、Chrome DevTools MCP 深度对比,开发者到底该用哪个?
2026年AI浏览器选型指南:Ego Lite专注多Agent协同(Mac优先),Tabbit国产首选,原生支持Windows与Codex控制;Chrome DevTools MCP非浏览器而是开发者利器,深度集成Console/Network/Performance调试能力,让AI真正“看懂并验证”前端代码。
1389 3
|
14天前
|
JSON 程序员 数据格式
最新版Notepad++下载、安装、配置保姆级教程(附官网安装包)
Notepad++ 是一款免费开源、轻量快速的 Windows 文本编辑器,支持多标签、语法高亮、代码折叠与宏录制,体积小、启动快、资源占用低,兼容 x64/x32/ARM 架构,是程序员和文字工作者的高效利器。
2759 0
|
7天前
|
安全 应用服务中间件 Go
PHP2Shell 漏洞拆解:WordPress 与 nginx 为何中招
PHP2Shell 双 RCE 已遭在野利用:WordPress、Drupal 全在射程内,nginx 其实另有洞。拆成因与修复顺序
PHP2Shell 漏洞拆解:WordPress 与 nginx 为何中招
|
14天前
|
安全 Linux 芯片
【万字长文】Ollama下载、安装、配置、使用保姆级教程(2026最新图解)
Ollama 是一款免费开源的本地大模型运行工具,支持 DeepSeek、Qwen 等主流模型,一条命令即可下载运行。2026 最新版 v0.35.1 官方安装包(1.47GB)已提供国内直连下载,纯本地、离线可用、无广告、无隐私泄露风险。
1322 5
|
7天前
|
开发者 索引
DeepSeekHarness大肥鱼自带插件市场了?加个地址就能用
Open Plugin Market 是一个开放插件索引平台,收录800+优质DSH插件,支持分类浏览、智能推荐与随机发现。无需安装市场,粘贴索引地址即可一键接入,网页版直访 dshopen.org,助力小开发者被看见。(239字)
1527 1
DeepSeekHarness大肥鱼自带插件市场了?加个地址就能用
|
5天前
|
安全 程序员 应用服务中间件
PHP 被曝两大致命漏洞,请所有程序员抓紧做这件事!
PHP 官方发布了紧急安全更新,一口气修复了两个严重漏洞。如果网站和服务器用了 PHP 应该怎么处理?漏洞的原理是什么?本文给你讲清楚
659 0

热门文章

最新文章