## 背景引入

MYSQL中数据表A,在删除了一半的数据后,发现表空间的大小并没有减少,这是什么原因导致的呢?

定义

当对一定量数据执行delete操作时,MySQL将数据删除后进而导致页合并或者页删除,生成空闲空间,并未将空闲空间返还给操作系统,而是将当前空间标记为"可复用",当有新的数据插入时,则不会重新申请空间,而是插入到"可复用"空间中,这种"可复用"空间,称之为数据空洞。

复现背景

前提

  • 使用innodb
  • MYSQL版本>=5.6

解释:从 MySQL 5.6 开始,InnoDB默认采用独立表空间

我使用的版本是:

步骤

  1. 获取MYSQL存放目录(连接MYSQL后使用)

    SHOW VARIABLES LIKE 'datadir';

    结果例如:

  2. 拼接目录找出文件

    例如dora库中的emp表即为D:\MySQL\datas\Data\dora\emp.ibt

未删除所有数据前的情况

文件大小

记录数

删除所有记录后的情况

文件大小

记录数

底层原理(delete执行的逻辑)

没有提server层的过多逻辑

  1. 确定要删除的记录或数据页

    • 当执行 DELETE 语句时,MySQL 会根据 WHERE 条件确定需要删除的具体记录。
    • 如果没有索引支持,可能会进行全表扫描,效率较低。
    • 如果有合适的索引,MySQL 会通过索引快速定位到需要删除的记录。
  2. 删除数据和相关索引
    • 删除操作不仅仅是删除数据行,还需要更新与这些数据相关的索引。
    • 索引中的对应条目会被删除,以保持索引的准确性和一致性。
  3. 触发页合并
    • 当删除操作导致数据页或索引页的空间利用率低于一定阈值时,InnoDB 会触发页合并操作。
    • 页合并会将相邻的空闲页合并成更大的连续空闲页,减少碎片化,提高存储效率。
    • 页合并通常在后台线程中进行,以尽量减少对当前事务的影响。
  4. 标记释放的空间为可复用
    • 删除后释放的空闲空间不会立即返还给操作系统,而是标记为可复用
    • 这些空闲空间会被优先用于后续的插入操作,减少磁盘 I/O,提高性能。

原因

原因正是删除后释放的空闲空间不会立即返回给操作系统

数据空洞的好坏

首先必须说明,需要辩证看待问题,这么设计是存在好处的:

  1. 减少了跟操作系统申请空间的次数(小幅度提高性能)
  2. 也减少了归还空间给操作系统(加快了像delete或者update的执行速度)

归根到底减少了磁盘IO

坏处则是:

  1. 磁盘空间浪费:

    1. 在软件与软件之间,由于MYSQL数据空洞会占用一定的磁盘空间,会导致其他软件出现空间不足等等问题
    2. (最最重要),在MYSQL内部也会出现问题:innoDB在MYSQL5.6后是独立表,数据空洞会导致占用掉一定的磁盘空间,而由于是独立表空间,这部分空间只能我们自己这张表使用,其他表无法利用也就会出现问题啦
  2. 查询性能下降:

    1. 数据空洞会影响查询性能,特别是在使用索引时。因为:
    2. 空洞使得数据页分布不连续,查询时磁盘 I/O 操作会更耗时(空洞导致IO更偏向随机IO了,IO成本相比于顺序IO来说耗时更长)来加载相关页。

如何规避掉数据空洞问题?

我们的思路是先分析数据空洞产生的方式,再进一步尝试降低对应的频率:

数据空洞产生的方式:

  1. 删除操作
  2. 更新索引字段
    • 更新索引字段时,实际上会执行删除旧值和插入新值的操作,容易产生数据空洞。对于需要频繁更新的字段,尽量避免为其创建索引。

如何规避

  • 对于删除操作:其实大多数数据库表设计的逻辑删除is_del已经帮我们解决掉了,只要场景适合即可
  • 对于索引更新:自然是减少频率了

参考资料

MySQL数据空洞:原因、影响与解决方法-CSDN博客

什么是MySQL数据空洞?-CSDN博客

如何解决掉数据空洞问题?

下集见分晓

MYSQL数据空洞解析的更多相关文章

  1. (转)mysql数据文件解析

    一 数据文件 在 MySQL中每一个数据库都会在定义好(或者默认)的数据目录下存在一个以数据库名字命名的文件夹,用来存放该数据库中各种表数据文件.不同的 MySQL存储引擎有各自不同的数据文件,存放位 ...

  2. android开发中 解决服务器端解析MySql数据时中文显示乱码的情况

    首先,还是确认自己MySql账户和密码 1.示例  账户:root   密码:123456   有三个字段   分别是_id  .username(插入有中文数据).password 1)首先我们知道 ...

  3. MySQL数据导出导入【转】

    MySQL基础 关于MySQL数据导出导入的文章,目的有二: 1.备忘 2.供开发人员测试 工具 mysqlmysqldump 应用举例 导出 导出全库备份到本地的目录 mysqldump -u$US ...

  4. Mysql binlog日志解析

    1. 摘要: Mysql日志抽取与解析正如名字所将的那样,分抽取和解析两个部分.这里Mysql日志主要是指binlog日志.二进制日志由配置文件的log-bin选项负责启用,Mysql服务器将在数据根 ...

  5. mysql数据表增删改查

    http://www.runoob.com/mysql/mysql-tutorial.html 一.MySQL 创建数据表 创建MySQL数据表需要以下信息: 表名 表字段名 定义每个表字段 语法 以 ...

  6. Mysql数据实时同步

    企业运维的数据库最常见的是 mysql;但是 mysql 有个缺陷:当数据量达到千万条的时候,mysql 的相关操作会变的非常迟缓; 如果这个时候有需求需要实时展示数据;对于 mysql 来说是一种灾 ...

  7. Mysql索引使用解析

    摘自:http://blog.chinaunix.net/uid-25063573-id-3032578.html Mysql索引使用解析 1.索引作用 在索引列上,除了上面提到的有序查找之外,数据库 ...

  8. MySQL 数据表操作

    MySQL 数据表操作 创建MySQL数据表需要以下信息: -表名: -表字段名: -定义每个表字段: 一.创建数据表 1)mysql> create  table  table_name (c ...

  9. logstash使用template提前设置好maping同步mysql数据到Elasticsearch5.5.2

    上篇blog说到采用logstash-input-jdbc将mysql数据同步到ES(http://www.cnblogs.com/jstarseven/p/7704893.html),但是这里有一个 ...

  10. MySQL binlog格式解析

    MySQL binlog格式解析   binlog想必大家都不陌生,在主从复制或者某些情况下的数据恢复会用到.由于binlog是二进制数据,要查看一般都借助mysqlbinlog工具.这篇笔记分析了b ...

随机推荐

  1. Jx.Cms开发笔记(三)-Views主题动态切换

    效果展示 我们可以在后台动态切换主题 目前Jx.Cms有两个主题,其中一个是默认主题,另一个是仿的Blogs主题. 我们可以通过点击启用按钮来动态切换两个主题. 实现方法 首先写一个实现IViewLo ...

  2. canvas(二)直线样式和虚线

    1.设置直线线帽的样式 相关语法:ctx.lineCap,通过赋值形式来设置直线线帽的样式,他有以下3个值: 值 说明 butt 默认 round 圆形线帽 square 正方形线帽 <scri ...

  3. 聊一下怎么十分钟速水CVE

    题目是真的.今天晚上刚接触关于CVE的审计和提交.只能说:牛逼的是真牛逼,水的是真水. 我接下来教你,怎么在10分钟里找到一个CVE的中危漏洞并且提交.然后你就可以去咸鱼接单了,一个一铂快 打开htt ...

  4. 再也不用写请求HttpHelper了,HttpClient帮助你

    前言 在C#7.1之后,net推出HttpClient类代替WebRequest, HttpWebRequest, ServicePoint, and WebClient ,先来看下他们在以前的作用 ...

  5. 面试官:DNS解析都整不明白,敢说你懂网络?我:嘤嘤嘤!

    一.写在开头 在OSI七层协议模型中应用层是距离我们最近,且日后开发使用到最多的一层,在上一篇博文中我们已经学习了应用层中的HTTP协议,在本文中我们再一起来学一下DNS.啥?DNS不是很了解?那还不 ...

  6. git 忽略某些文件

    如果git项目里没有  '.gitignore' 文件,则需要执行下面的操作,生成一个 生成 '.gitignore' 文件 1. git bash  打开git窗口 执行:touch .gitign ...

  7. jdk安装-windows和linux

    下载:见此博客https://www.cnblogs.com/zn19961006/p/12857930.html 一.windows安装 1.很简单,运行exe,然后一直下一步 选安装路径. 注意: ...

  8. Verilog3_组合逻辑电路

    组合逻辑电路设计方法 使用assign语句: 描述简单的组合逻辑电路 使用always块: 描述复杂的组合逻辑电路 要点: 只在一个always模块中对某一变量进行赋值: 将所有敏感变量列在敏感变量列 ...

  9. 「V 曲闲谈」《hello&bye,days》——记这周

      这周破事儿浓度真的,情绪渗透压巨大失调.   完全没有曲析啊喂,顶多当个阅读时 BGM.() 两度失眠   "砰--"   朦胧之中看见斜上方的室友起身.   "砰- ...

  10. 《CUDA编程:基础与实践》读书笔记(4):CUDA流

    1. CUDA流 一个CUDA流指的是由主机发出的在一个设备中执行的CUDA操作序列.除主机端发出的流之外,还有设备端发出的流,但本文不考虑后者.一个CUDA流中的各个操作按照主机发布的次序执行:但来 ...