套路的人心:MySQL使用delete删除数据的正确套路!
为啥MySQL不建议用DELETE删数据?说白了,你可能还真不配用它
阿里面试问这个问题,不是***难你,是想看看你到底是CRUD民工,还是能把数据库当朋友用的老炮儿。
一、DELETE听起来很清爽,用起来往往“祭天”
首先,DELETE不是不能用,而是你得知道它的代价,你得知道它背后到底做了啥。很多人写个SQL就是:
DELETE FROM user WHERE status = 'inactive';
看着清清爽爽,执行完了控制台还给你来句“Query OK, 1000000 rows affected”,然后服务嘎的一声宕机,QPS跌成狗,DBA头发开始谢落,领导问你是不是手滑了。
这波操作,线上的锅你得背,简历得更新,关键是你还不知道错哪了。
二、MySQL DELETE底层到底干了啥?
MySQL的DELETE,其实背地里非常重,尤其是你删的是InnoDB表,它做的事情比你以为的多得多:
1. DELETE不是物理删除,而是行级删除 + 日志记录
InnoDB是支持事务的,它不能说删就删,得有回滚能力。所以它做了这些事:
- 标记要删除的行
- 写UNDO日志(为了事务回滚)
- 写REDO日志(为了崩了还能恢复)
- 更新索引(主键+二级索引全部都得动手)
- 最后才是真正的标记行已删除
你以为你在“清空”,其实你在走一整套事务机制,跟离婚一样,得先申请、备案、调解、走流程,最后判离。全表DELETE就相当于办集体离婚,政务大厅都能爆了。
2. 删除的行不会马上释放空间
InnoDB做的是MVCC(多版本并发控制),DELETE之后的数据并不会立马消失,旧版本还留着,事务没提交前你还能查出来。
即便提交了,磁盘空间也不会释放。你DELETE 100W 行,磁盘占用可能一个字节都不降。你得等它自己触发PURGE流程,或者你主动做OPTIMIZE TABLE,才能回收。
大哥你删了还得自己收拾战场,这叫啥?这叫“你杀人你还得擦血迹”,你说累不累。
三、DELETE的几个雷,踩了炸得你妈都不认识你
1. DELETE大表,直接锁死线上系统
来,讲个我亲历的事儿:
某年某月某日,一个实习生(不是我)要清除3个月前的订单,写了个:
DELETE FROM orders WHERE create_time < '2023-01-01';
然后按下执行,MySQL瞬间CPU飙升,表锁死,所有查订单的接口直接502。客服在工位上哭,运维在电话里骂,领导进会议室打我(虽然不是我干的)。
问题在哪?
- 没分页
- 没用LIMIT
- 没用索引(是的,create_time没建索引)
- 没归档策略
- 一条SQL,把整个库怼瘫了
DELETE默认是行锁,但你删太多行,它可能升级为表锁,你那点小QPS根本扛不住。
2. DELETE会拖垮redo log
InnoDB写redo log有缓冲区,有write-ahead机制,但DELETE一多,日志量陡增,缓存直接爆掉,IO跟不上,写盘阻塞。
你以为是DELETE卡住了,其实是磁盘在疯狂转,binlog、undo log、redo log都挤在那排队,宛如12306春运抢票页面。
3. DELETE影响主从延迟
大厂主从架构都跑得飞快,但DELETE一跑,binlog刷一堆,从库延迟直接上天。
主库写了一个小时,从库还在回放那条SQL。你要是还有读写分离,那这时候读到的数据都是旧的,订单显示“未支付”,其实人家早付款了,分分钟投诉你虚假交易。
四、为啥阿里不建议用DELETE?人家是拿真实流量砸过来的
别说阿里,字节、腾讯、京东都一样,对DELETE有明确要求。
像阿里的数据量,一张表动辄上亿数据。你一句DELETE,全删了,分库分表的路都白走了,业务线可能一个月都恢复不过来。
所以在大厂,DELETE基本上有以下规定:
- 禁止在主库DELETE超过N条记录
- DELETE必须带LIMIT,必须走索引
- 大表DELETE必须走归档逻辑,不允许直接删
- 定时归档走独立脚本 + 延迟消费
- 回收策略用DROP分表 + 重建表
而不是写个DELETE FROM xxx WHERE xxx
,那是作死速通路线。
五、那不DELETE,我咋清数据?盘他!
行,那我们来说替代方案。这才是重点,实战部分来了。
1. DELETE + LIMIT + SLEEP 慢慢删
这个是经典套路:
-- 分批删除,每次只删1000条
DELETE FROM orders WHERE create_time < '2023-01-01' LIMIT 1000;
-- 循环 + SLEEP 1s 避免IO暴冲
写成存储过程、脚本,跑定时任务,慢慢挪,你像倒垃圾一样,别全往楼下扔,分批分类处理。
2. 归档转移 + 表切换
这个大厂玩得飞:
- 新表 orders_archive
- insert into orders_archive select * from orders where create_time < xxx;
- insert成功后,DELETE or TRUNCATE or DROP老数据
这种归档方案,可以挂在Kafka消费层、可以异步拉数据,不影响主库压力,还能跑到其他磁盘上,便于做冷热分离。
3. TRUNCATE + 表分区 / 分表策略
你想清空数据,直接TRUNCATE,比DELETE干净利索。但条件是:
- 表不能有外键
- 你要敢直接扔整个表
那咋办?用分表。
订单表 orders_202406、orders_202405、orders_202404
清理2024年4月的订单?直接DROP TABLE orders_202404
,嘎嘣脆,不走DELETE逻辑,干净直接。
六、再说一次,DELETE不是错,错的是你没搞清楚你的库值多少钱
兄弟,MySQL是你用的最久的朋友,却也最容易被你轻视。你说DELETE就是删除,那你可真把自己当CRUD Boy了。
你得问问自己:
- 这张表多大?
- 有多少行?
- delete操作是否走索引?
- 有没有binlog回放压力?
- 是主库还是从库执行?
- 是否有归档机制?
你不搞清楚这些,就动手删?那跟不看红绿灯上高速一个意思,迟早出事故。
七、收个尾巴:DELETE只是个按钮,背后是命运的齿轮
阿里面试问这个问题,其实是想看看你对数据库有没有“敬畏之心”。不是说你不能删,而是你得知道,你删的不是数据,你删的是稳定,是成本,是流量,是你同事的加班时间。
想清楚这个,再谈什么SQL性能优化、什么数据治理,才有意义。
最后给个套路总结,面试装X必背:
“MySQL DELETE并不推荐直接在大表上用,是因为InnoDB的事务机制、日志机制、MVCC机制决定了DELETE开销大、性能差、延迟释放空间、容易引发主从延迟、锁表等问题。通常建议使用分批DELETE + LIMIT,归档策略、分表DROP、TRUNCATE替代,避免直接操作线上表,保障系统稳定性。”
拿去背,背完你就是面试场上的“数据库王者”。
套路的人心:MySQL使用delete删除数据的正确套路!的更多相关文章
- MYSQL中delete删除多表数据
MYSQL中delete删除多表数据 DELETE删除多表数据,怎样才能同时删除多个关联表的数据呢?这里做了深入的解释: 1. delete from t1 where 条件 2.delete t1 ...
- 一句DELETE引发的加班(Mysql 恢复Delete删除的数据)
本机用的Navicat连mysql测试DB又连了正式DB,因为本地与正式要频繁操作所以都打开了很多查询,本来要DELETE删除测试DB的数据,没看清在正式环境执行了.共删除了325条数据,然后在网上找 ...
- window下Mysql 恢复Delete删除的数据
转载:https://www.cnblogs.com/q149072205/p/11940591.html 本机用的Navicat连mysql测试DB又连了正式DB,因为本地与正式要频繁操作所以都打开 ...
- 什么?还在用delete删除数据《死磕MySQL系列 九》
系列文章 五.如何选择普通索引和唯一索引<死磕MySQL系列 五> 六.五分钟,让你明白MySQL是怎么选择索引<死磕MySQL系列 六> 七.字符串可以这样加索引,你知吗?& ...
- SQL中CRUD C——create 添加数据 R——read 读取数据 U——update 修改数据 D——delete 删除数据
在SQL server中对数据库的操作: 删除表:drop table 表名修改表:alter table 表名 添加列add 列名 列类型alter table 表名 drop column 列名 ...
- MYSQL中delete删除多表数据与删除关联数据
在mysql中删除数据方法有很多种,最常用的是使用delete来删除记录,下面我来介绍delete删除单条记 录与删除多表关联数据的一些简单实例. 1.delete from t1 where 条件 ...
- MySQL不建议delete删除数据
InnoDB存储架构 从这张图可以看到,InnoDB存储结构主要包括两部分:逻辑存储结构和物理存储结构. 逻辑上是由表空间tablespace -> 段segment或者inode -> ...
- Influx Sql系列教程七:delete 删除数据
前面介绍了使用insert实现新增和修改记录的使用姿势,接下来我们看一下另外一个简单的使用方式,如何删除数据 1. delete 语句 delete的官方语法如下 DELETE FROM <me ...
- delete删除数据造成归档日志增加,操作系统空间不足导致数据库hang住
业务需求,对日志表历史数据进行清理.历史表均很大,使用delete 操作删除90天前的数据. 第一部分:快速删除数据 SQL> alter table CC.F_LOG parallel ; S ...
- MySQL 创建和删除数据表
创建MySQL数据表需要以下信息: 表名 表字段名 定义每个表字段 语法 以下为创建MySQL数据表的SQL通用语法: CREATE TABLE table_name (column_name col ...
随机推荐
- C#之MethodImpl(MethodImplOptions.Synchronized)
[MethodImpl(MethodImplOptions.Synchronized)] 是 C# 中用于指定方法同步的一个特性,它控制方法的执行方式,确保在多线程环境下某个方法的执行是线程安全的.它 ...
- C#中扩展方法无法获得多态性的行为
在C#中,扩展方法(Extension Methods)是一种用于给现有类型添加新方法的技术.但是,扩展方法无法实现多态性的行为,因为它们是静态方法,它们的行为是在编译时确定的,而不是在运行时. 多态 ...
- systemctl服务文件管理指南
systemctl命令概述 systemctl是 Linux 系统中用于管理系统服务的命令,是systemd初始化系统的一部分.它可以用于启动.停止.重启和重新加载服务,查看服务状态以及设置默认启动级 ...
- @FeignClient注解自定义接口超时时间
问题描述 每个微服务都有统一的接口超时时间设定,但也存在一些特殊的业务场景,其接口需要较长的超时时间,比如:导出excel报表.上传文件.拉取业务报表数据等等.此时,默认的超时设置就不能满足需求, ...
- pythonOCC 将二维坐标转化为三维坐标
OCC 当中提供了多种方式转换 直接转换为三维坐标 使用 V3d_View.ProjReferenceAxe()会返回有6个元素的元组,前三位分别对应 XYZ 例子 self._display.Vie ...
- frp实现内网穿透访问内网多台Linux服务器
本文主要记录笔者在使用frp实现内网穿透访问内网多台Linux服务器的全过程,包括公网服务器的配置.frp服务端.客户端的下载与配置,以及配置systmctl来实现系统级启停frp,并记录我遇到的一些 ...
- 2023人形全能赛竞速机器人mega代码
mega // @Author : Hcm #include <LobotServoController.h> // 舵机板通信 #include <OneButton.h> ...
- Kubernetes存储-Ceph存储
Kubernetes存储-Ceph存储 原文链接:https://www.qikqiak.com/k8strain/storage/ceph/#_11 简介 Ceph 是一个统一的分布式存储系统,提供 ...
- Lecture 1 NN,KNN
INT305 Machine Learning Lecture 1 Outline of this course ·Suprevised Learning Nearest Neighbors 近邻 D ...
- BAPI_OUTB_DELIVERY_CREATE_SLS、BAPI_OUTB_DELIVERY_CONFIRM_DEC 创建交货单,交货单过账
FUNCTION zsd_dn_create1. *"-------------------------------------------------------------------- ...