一、表的空间是怎么回收的?
InnoDB包含了两个部分:表结构定义和数据;在MySQL8.0前表结构是存在以.frm为后缀的文件里,8.0及之后已经允许放在系统数据表中,因为表结构占用空间很小。
1.怎么控制InnoDB表的表结构存放位置
innodb_file_per_table : MySQL5.6.6之后默认是ON
ON:每个InnDB的表数据存在一个以.ibd为后缀的文件中;
OFF:表的数据放在系统共享表空间,也就是跟数据字典放在一起;
建议设置
建议设置为ON,因为如果需要删除表,设置为ON,执行drop table 命令也会删除.ibd文件,会回收表结构的空间;设置为OFF虽然把表删了也不会回收表结构的空间。
2.数据的删除流程
DQL(查询):查询数据:select语句(最常用)
DML(操纵):表数据的增删改,insert、update、delete
DDL(定义):对表的增删改,create、drop、alter
DCL(控制):grant授权、revoke撤消等
TCL(事务控制):commit事务提交、rollback回滚事务
(1)什么叫数据的“空洞”?
数据在删除的时候,表结构InnDB的索引是以B+tree的形式储存的,当删除某个数据时,只会把该子叶子节点的数据标记,不会立即释放空间,只有有一条记录的索引等于该值时才会复用这个位置。
我们直到mysql都是以数据页的形式储存的,如果整个数据页都被标记,那么新增数据在该数据页的范围值内,就可以直接复用。
当相邻两个数据页的数据都比较少时,两个数据页的数据会合在一起,腾出一个新的数据页被标记为可复用。
delete命令删除表时,都会把删除的位置标记,认为是可复用,我们把那些没有被复用到的位置称为空洞。
(2)怎么解决空洞问题呢?
重建表
2.怎么重建表?
用语句:
alert table t engine=InnoDB
(1)请简述重建表的过程:
在MySQL5.6之后,重建表支持Online DDL(在重建表时,可以有DDL操作)的操作:
- 建立一个临时文件,记录扫描表t的数据页
- 用数据页表t的记录生成B+tree,记录临时文件
- 在生成记录临时文件的过程中,对表t的操作记录到日志文件 row log,
-把row log日志文件的记录写入到临时文件的得到逻辑上与表t相同的文件 - 用临时文件把表t替换
(2)DDL 之前是要拿 MDL 写锁的,这样还能叫 Online DDL 吗?
在执行alert之后是会获取MDL写锁的,但是在复制数据的时候会退化成MDL读锁,这个时候是可以修改数据的。
为什么不直接放开MDL锁呢?
因为要禁止其它线程对表DDL
所以在整个DDL过程来说,锁的时间非常短,所以可以看做是Online DDL
(3)在生产中一般怎么使用
在生产中一般数据量比较大的数据库来说的话,因为会对整个表扫描和建立临时文件是非常消耗io和cpu的,建议使用Githud开源的gh-ost
gh-ost是什么?
是一个开源的缩小表空间的工具。
3.DDL online 和 inplace的区别
DDL online和inplace是包含与被包含的关系,online一定是inplace,反之亦然。截止到 MySQL 8.0,添加全文索引(FULLTEXT index)和空间索引 (SPATIAL index) 就属于这种情况
alter table t add FULLTEXT(field_name);
这个过程是 inplace 的,但会阻塞增删改操作,是非 Online 的。
二、思考题
假设现在有人碰到了一个“想要收缩表空间,结果适得其反”的情况,看上去是这样的:一个表 t 文件大小为 1TB;对这个表执行 alter table t engine=InnoDB;发现执行完成后,空间不仅没变小,还稍微大了一点儿,比如变成了 1.01TB。你觉得可能是什么原因呢 ?