腾讯|什么?还在用delete删除数据《死磕MySQL系列 九》( 二 )



猜一下创建的evt_sms表结构定义存储在哪里呢?
在information_schema库里边的TABLES中 , 执行查询SELECT TABLE_NAMETABLE_COMMENT FROM TABLES WHERE TABLE_TYPE='BASE TABLE';

我们自定义的表类型是TABLE_TYPE 。说了这么是为了解释如果把innodb_file_per_table设置为off , 则表数据也会存放在这里 。
问题:如果数据存在放共享表空间中 , 表删除了 , 空间会删除吗?
答案是不会的 。
参数innodb_file_per_table设置为on数据存储在哪里呢?
一般情况下是在var/lib/mysql中 , 会看到你创建的数据库 , 进入到数据库中就能看到一张表对应一个ibd文件 。
数据就是存储在这里 。

【腾讯|什么?还在用delete删除数据《死磕MySQL系列 九》】结论
在项目开始阶段 , 切记将innodb_file_per_table设置为on , 这是正确的做法 。
二、数据删除流程现在你应该知道Innodb存储引擎用的是B+树数据结构 , 如下图 。

如果现在删了主键ID为4的这条记录 , Innodb引擎会把ID为4的这条记录标记为删除 , 如果之后再插入ID为4的记录 , 可能会复用这个位置 , 但磁盘文件大小并不会缩小 。
隐式字段
这里就牵扯到了mvcc中的一个知识点 , MVCC实现原理是由俩个隐式字段、undo日志、Read view来实现的 。
上文说的标记删除就是隐式字段中的delete flag , 即记录被更新或删除 , 这里的删除并不代表真的删除 , 而是将这条记录的delete flag改为true 。

在MVCC:听说有人好奇我的底层实现这篇文章中也给大家留下了一个伏笔 , 数据库的删除是真的删除吗?问题:删了一个数据页的所有数据会怎么样
跟单条数据是一样的 , 整个数据页都是可以复用的 。
记录的复用是仅限于符合范围条件的数据 , 例如上文删除的ID为4这条记录 , 如果在插入ID为4就会复用 。
这里需要给大家再聊一个新的知识点页合并 , 若相邻的两个数据页利用率都很低 , 系统就会把这两个数据页合并到一个页上 , 另一个数据页就会标记为可复用 。
问题:使用delete把整个表的数据都删除了会怎么样
答案是 , 所有的数据页都会标记为可复用 , 但是磁盘文件大小是不会改变的 。
三、实践全表删除表文件大小不改变
经过添加数据后表数据已经达到近100W了 , 文件大小已经达到108M 。
扩展
这里大家应该能看见stopped , 就是执行命令ctrl + z来的 , 作用是开始我们在MySQL窗口里边 , 但不想退出MySQL窗口查看MySQL表文件大小 , 然后就可以执行这个命令结束任务 。
查看完后可以在执行fg返回到MySQL窗口 。

问题:Linux如何把文件单位显示为M
假设刚刚直接执行ll命令查看文件 , 那么就需要手动计算文件大小 , 很不方便 。
执行ll -h命令则可以直观的看到文件大小 。

删除数据查看磁盘文件是否缩小

为了直观看大文件大小变化 , 咔咔直接把表里边的数据全部删了 , 再看文件大小 , 还是108M 。 文件大小是没有变化的 。 四、如何正确的减少磁盘文件在第三小节中 , 我们演示了删除了100W数据后文件大小是没有改变的 , 也就是空洞问题影响的 , 接下来就解决这种问题 。
问题:空洞是如何产生的?
到了这里都应该知道空洞是因为大量的增删改造成的 。
解决思路
你可以新建一个evt_sms_copy表 , 然后根据主键ID递增的顺序 , 把数据从evt_sms读入evt_sms1中 。