一:概念

  - 这里,我们还是针对 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. 编程用sort进行排序,然后从最后一个元素开始判断,去重

    a=[,,,,,,,,,,,,,,] a.sort() last=a[-] ,-,-): if last==a[i]: del a[i] else: last=a[i] print(a)

  2. 2019-06-03 校内python模拟题解(所有非原题)

    一起来女装吧 本题改编自USACO(USA Computing Olympiad) 1.1节的第一题 (感谢lsy同学对本题题面的贡献) 直接计算就好了 chr:将ASCII码转成字符 ord:字符对 ...

  3. 小程序tabBar的使用

    这个selectedIconPath一定要写,否则选中的那个图片是不会显示的 下面是不写的现象: onTabItemTap的使用---下面的现象说明:只有tab值向哪个页面才会触发.

  4. C++的面向对象的Dijkstra写法

    C++的面向对象的Dijkstra写法 面向对象特点的充分使用 清晰的逻辑 简洁的图输入 程序 面向对象特点的充分使用 清晰明确的类实现 class Edge(边的实现) class Req (路由请 ...

  5. Hibernate 基本使用

    Hibernate框架概述 一.什么是框架 软件的一个半成品,已经帮你完成了部分功能. 把一些不确定的东西,按照框架要求,达到相应的功能 Hibernate是JavaEE技术三层架构所用到的技术 二. ...

  6. Python_BDD概念

    BDD概念 全称 Behavior-driven development 中文 行为驱动开发 概念 是敏捷软件开发技术的一种,鼓励各方人员在一个软件项目里交流合作,包括开发人员.测试人员和非技术人员或 ...

  7. DataSync 异构数据同步

    RAC, Data Gurad, Stream 是Oracle 高可用性体系中的三种工具,每个工具即可以独立应用,也可以相互配合. 他们各自的侧重点不同,适用场景也不同. RAC 它的强项在于解决单点 ...

  8. 如何交叉编译openssl库?

    1. 获取源码 wget https://www.openssl.org/source/openssl-1.0.2s.tar.gz 2. 解压源码 tar xvf openssl-1.0.2s.tar ...

  9. Java并发包线程池之ForkJoinPool即ForkJoin框架(一)

    前言 这是Java并发包提供的最后一个线程池实现,也是最复杂的一个线程池.针对这一部分的代码太复杂,由于目前理解有限,只做简单介绍.通常大家说的Fork/Join框架其实就是指由ForkJoinPoo ...

  10. Bitmap之extractAlpha函数抽取alpha值

    package com.loaderman.customviewdemo; import android.app.Activity; import android.graphics.Bitmap; i ...