mysql中的数据分为表结构数据和表真实数据, 在MYSQL8.0 之前, 表结构是存储在单独的.frm后缀文件中, 8.0之后, 会存储在系统数据表中。

innodb_file_per_table

参数 innodb_file_per_table 设置成ON 会使用单独的frm文件存储表结构, 设置成off是使用系统数据表存储表结构。
建议这个参数设置成ON . 因为表结构很小,使用单独的frm文件,方便维护

删除表操作 drop table . 此命令会删除表空间(表数据和表结构)
但是delete删除表中部分数据, 这样会出现表文件的大小没有变小的情况;

删除几行记录

如果我们使用delete 命令删除几行数据, mysql只是把这几行的数据打个删除的标记, 实际上这几行的数据还在原来的位置, 所以表文件的大小没有变化。
打了标记的行, 如果再次插入了新数据,新数据刚好在标记删除行的位置,mysql就会复用这标记删除的空间,覆盖更新。

删除整个数据页

如果我们删除的数据占满了一个数据页,mysql会把整个数据页标记删除, 如果要新增新的的数据页, mysql会复用这个标记删除的数据页, 数据页的复用和行空间的复用不一样, 行的复用必须要新的行和标记删除的行在同样的位置才能复用, 数据页没有这个限制。

插入数据的时候也会导致页数据存储中间有空洞

如果我们的索引是自增的, 比如主键, 那么插入的时候, 数据是紧凑的。 但是如果索引字段的值是随机的UUID,每次插入的时候,都要在B+树中确定位置找到对应的数据页,插入到数据页中。

如果要插入的数据页已经满了,此时就会导致数据页的分裂情况, 会把插入的数据页分裂成两个数据页。 这两个数据页都没有存满,但是还是占用16K的空间, 就会导致内部的数据不紧凑。

更新数据的操作

可以理解成 删除一个数据,再插入一个数据, 如果删除和插入的位置不一样,同样会导致数据不紧凑的空洞情况

重建表alter table A engine=InnoDB

如果表的数据不紧凑的情况太多了, 这个时候就如果来人工清除这行空洞, 操作流程大致如下:

  • 新建一个结构一样的表, 只是表名不一样
  • 把旧表数据一行行复制进新表中,这样就会新表就是比较紧凑的了。
  • 再通过修改表名,使用新表替换旧表。

上面是操作的基本流程, mysql提供了命令可以来自动完整这个流程 alter table A engine=InnoDB 但是在MYSQL5.6之前的版本中, 这个命令的执行过程中, 如果有新的数据插入会导致数据丢失(因为可重复读的问题) 。 但是在5.6版本开始订正了这个问题, 订正的操作很简单:

  1. 就是使用一个日志文件, 先记录下载在这个命令执行期间进行的操作
  2. 在新表完成数据同步后, 再从日志文件中获取到期间的所有操作,在新表上执行一遍就可以了

所以上述的重建表操作在mysql5.6之后的版本就是Online操作了。

但是ALTER操作是DML操作, 会获取MDL写锁,会锁住操作的表,锁住之后就无法进行数据行的写操作了。 但是MYSQL也有解决方式, 就是DML写锁获取成功会后退化成读锁。 这样其他的事务可以对这个表的数据进行读写操作了,但是其他的事务又无法对这个表的结构进行写操作了, 因为MDL读锁 还没有释放。

由于在进行数据的转移操作的时候, 旧表还可以进行数据的正常读写操作, 可以并行进行, 所以这个操作是Online的

Inplace

这个是与Online对应的概念, 使用 alter table t engine=innodb,ALGORITHM=copy;
使用这个命令重建表就是Inplace操作, InPlace操作时候会使用DML锁锁住相关的表, 这样这个表就不支持修改和插入了,但是支持查询操作。

Inplace 操作不会使用临时表, 而是在原表的空间重新创建索引B+tree.

如果我们给一个大表增加一个全文索引, 在生成索引的过程中,整个表示被锁住的, 无法进行写入操作,只能进行读取操作。 所以新增索引也是属于Inplace类型。 这里只是说到全文索引。

Alter 操作有许多是Online的。 如果alter 操作在事务中间, 默认会在alter之前会提交事务,alter会在事务外执行 。

注意:

重建表操作,新建的表并不是一定紧凑的,它会把每个数据页预留1/16分。 这个预留是用来应对插入的,如果太紧凑了, 来一个插入就会导致数据页的分裂。

所以一个十分紧凑的表进行重建操作,会可能导致这个表的占用的空间反而变大了, 所以不要随便的执行这个操作。

Online 重建表会把重建过程中的操作记录到rowLog中, 表数据复制完成后会在新表中执行row log中的操作, 这个执行操作可能会导致新表的空洞不连续