一:概念

  - 这里,我们还是针对 MySQL 中应用最广泛的 InnoDB 引擎展开讨论。

  - 一个 InnoDB 表包含两部分,即:表结构定义和数据。

    - 在 MySQL 8.0 版本以前,表结构是存在以.frm 为后缀的文件里。

    - 而 MySQL 8.0 版本,则已经允许把表结构定义放在系统数据表中了。

    - 因为表结构定义占用的空间很小,所以我们今天主要讨论的是表数据。

二:表数据既可以存在共享表空间里,也可以是单独的文件。由参数 innodb_file_per_table 控制。

  - 概念

    - 这个参数设置为 OFF 表示的是,表的数据放在系统共享表空间,也就是跟数据字典放在一起。

    - 这个参数设置为 ON 表示的是,每个 InnoDB 表数据存储在一个以 .ibd 为后缀的文件中。

  - 从 MySQL 5.6.6 版本开始,它的默认值就是 ON 了。

    - 因为,一个表单独存储为一个文件更容易管理,而且在你不需要这个表的时候,通过 drop table 命令,系统就会直接删除这个文件。

    - 而如果是放在共享表空间中,即使表删掉了,空间也是不会回收的。 

三:数据删除流程

  - 数据

    - 

  - 删除

    - 假设,我们要删掉 300 的记录,InnoDB 引擎只会把 300 这个记录标记为删除。

    - 但是, 如果之后要再插入一个 在 300-500 之间的记录时,可能会复用这个位置。(磁盘文件的大小并不会缩小)。

    - 如果我们删掉了一个数据页上的所有记录,整个数据页就可以被复用了。(如果相邻的两个数据页利用率都很小,会整合两个数据页,一个数据页就被标记为可复用。)

  - 如果我们用 delete 命令把整个表的数据删除呢?

    - 结果就是,所有的数据页都会被标记为可复用。但是磁盘上,文件不会变小。

  - 结论

    - Delete 命令其实只是把记录的位置,或者数据页标记为了“可复用”,但磁盘文件的大小是不会变的。

    - 也就是说,通过 Delete 命令是不能回收表空间的。

    - 这些可以复用,而没有被使用的空间,看起来就像是“空洞”。

    - 实际上,不止是删除数据会造成空洞,插入数据也会。

      - 如果数据是按照索引递增顺序插入的,那么索引是紧凑的。但如果数据是随机插入的,就可能造成索引的数据页分裂。

      - 假设我要写入的 page A 已经满了,在插入一行数据,也会导致页分裂。

      - 另外,更新索引上的值,可以理解为删除一个旧的值,再插入一个新值。不难理解,这也是会造成空洞的。

    - 也就是说,经过大量增删改的表,都是可能是存在空洞的。

    - 所以,如果能够把这些空洞去掉,就能达到收缩表空间的目的。

四:重建表(去除空洞)

  - 如果需要重建表,那么你能想出他是如何构建表的?

    - 建立 临时表B,把 A 表数据根据递增的关系,放入 B 中,最后用 B 替换 A。完成重构。(A 的空间收缩,空洞消失)

  - 而在MySQL 5.6 版本开始引入的 Online DDL,对这个重建操作流程做了优化。

    - 流程

      - 建立一个临时文件,扫描表 A 主键的所有数据页。

      - 用数据页中表 A 的记录生成 B+ 树,存储到临时文件中。

      - 生成临时文件的过程中,将所有对 A 的操作记录在一个日志文件(row log)中。

      - 临时文件生成后,将日志文件中的操作应用到临时文件,得到一个逻辑数据上与表 A 相同的数据文件。

      - 用临时文件替换表 A 的数据文件。

    - 区别

      - 不同之处在于,由于日志文件记录和重放操作这个功能的存在,这个方案在重建表的过程中,允许对表 A 做增删改操作。

      - 这也就是 Online DDL 名字的来源。

五:如何重建表?

  - alter table t engine = InnoDB(也就是 recreate)

    - OnLine DDL

  - analyze table t

    - 其实不是重建表,只是对表的索引信息做重新统计,没有修改数据,这个过程中加了 MDL 读锁;

  - optimize table t

    - 等于 recreate+analyze。

《Mysql - 为什么表数据删掉一半,表文件大小不变?》的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. 做reacat小项目的过程(我感觉适合那种刚刚接触react感觉很深奥的亲们,通过这个可以建立一个很垃圾的项目,入门吧,往深处就需要自己再看了)

    需求:做一个react框架的前端框架(包括路由,请求后端等),大概就是做一个左边导航右边显示组件页面的东西,ui为material-ui 环境: 软件:vscode 包含的知识点:使用路由来导航,使用 ...

  2. 前端武器库之jQuery示例

    1.全选 反选 取消 相关知识点: - 选择器 - .prop $('#tb:checkbox').prop('checked'); 获取值 $('#tb:checkbox').prop('check ...

  3. c++ rapidjson读取json文件 解析

    库:链接:https://pan.baidu.com/s/1UChrgqLPJxKopyqShDCHjg  密码:3yhz #include <iostream> #include < ...

  4. elasticsearch update方法报错: Too many dynamic script compilations within, max: [75/5m]

    PUT _cluster/settings    {        "transient" : {            "script.max_compilations ...

  5. Java 多线程编程(锁优化)

    转:https://mp.weixin.qq.com/s/lDuguEhuWiLY8ofBRy3tZA 并发环境下进行编程时,需要使用锁机制来同步多线程间的操作,保证共享资源的互斥访问. 加锁会带来性 ...

  6. DES算法实现

    概述(团队项目) DES是一个分组加密算法,它以64位为分组对数据加密.同时DES也是一个对称算法:加密和解密用的是同一个算法.DES是一个包含16个阶段的"替换–置换"的分组加密 ...

  7. 2018-2019-2 20165312《网络对抗技术》Exp9 Web安全基础

    2018-2019-2 20165312<网络对抗技术>Exp9 Web安全基础 目录 Exp9_1安装Webgoat Exp9_2 SQL注入攻击 Numeric SQL Injecti ...

  8. openjudge计算概论-大整数加法

    /*=====================================================================1004:大整数加法总时间限制: 1000ms 内存限制: ...

  9. 通AI启示录,从一篇数学物理基础论文说起 原创: 关注前沿科技 量子位 今天 允中 发自 凹非寺

    通AI启示录,从一篇数学物理基础论文说起 原创: 关注前沿科技 量子位 今天 允中 发自 凹非寺

  10. NULL和nullptr

    NULL就是0 nullptr是空指针[c++11]