一:概念

  - 这里,我们还是针对 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. JSP+Oracle实现分页功能

    Oracle: create table load( id char(200) not null, title varchar2(100) not null, time varchar2(100) n ...

  2. 页面嵌套iframe时,怎样让iframe高度根据自身内容高度自适应

    总体思路是这样的,因为iframe里页面的内容是动态加载的,而且电脑屏幕宽度发生变化时,也得相应的去改变iframe标签的高度(如果高度确定就不用这么麻烦了): 首先,我们在父页面中定义一个方法,用来 ...

  3. Arts打卡第10周

    Algorithm.主要是为了编程训练和学习. 每周至少做一个 leetcode 的算法题(先从Easy开始,然后再Medium,最后才Hard). 进行编程训练,如果不训练你看再多的算法书,你依然不 ...

  4. LTDC/DMA2D——液晶显示

    1.显示器的基本参数 (1) 像素像素是组成图像的最基本单元要素,显示器的像素指它成像最小的点. (2) 分辨率一些嵌入式设备的显示器常常以“行像素值 x列像素值”表示屏幕的分辨率.如分辨率 800x ...

  5. Interacted Action-Driven Visual Tracking Algorithm

    文章来源:Attentional Action-Driven Deep Network for Visual Object Tracking   博士论文(2017年8月份完稿) http://s-s ...

  6. eclipse导入maven项目有红叉及pom.xml出错的问题的解决

    导入我们的项目的时候总会出现很多红叉,看着很难受,其实可以解决的(本人使用方法一解决)解决方法:1.先build project,然后右键项目->maven->update project ...

  7. 双缓冲技术局部更新原理之派生自SurfaceView

    package com.loaderman.customviewdemo; import android.content.Context; import android.graphics.Canvas ...

  8. PorterDuffXfermode之PorterDuff.Mode.MULTIPLY

    package com.loaderman.customviewdemo.view; import android.content.Context; import android.graphics.B ...

  9. Windows10+VMware Workstation Pro+Ubuntu 16.04+Hadoop-2.6.5+IDEA环境搭建(单机&伪分布式&集群)

    (注:下面出现的"czifan"为用户名,需替换成自己的用户名) 本篇博客是在实践该篇博客的过程中的一些补充和修改~ 0 - 安装VMware Workstation Pro 首先 ...

  10. CSS如何实现把鼠标放在行上整行变色

    CSS如何实现把鼠标放在行上整行变色: 在很多网站都有这样的效果,那就是当鼠标放在一个文章列表行的时候,此行就会显示与其他行不同的颜色,本站的文章列表也具有这样的效果,便于浏览者识别,非常人性化,下面 ...