ITPub博客

首页 > 数据库 > 数据库开发技术 > mysql每天一点点笔记(三)

mysql每天一点点笔记(三)

原创 数据库开发技术 作者:DBA修行之路 时间:2022-02-13 20:07:01 0 删除 编辑

文字表述

文字表述

文字表述

左右滑动查看更多



点击上方“蓝字”,发现更多精彩。





mysql每天一点点笔记(三)


今日内容

这是年后上班的第一个周末,年前和过年假期偷懒了,该是时候继续学习了,延续之前的知识点,笔记记起来。最近还是关于MySQL基础知识点的归纳总结。会详细了解一下MySQL数据记录的组成,数据页的逻辑架构,页目录的信息以及延伸出来的表空间碎片的清理方式,记录查找在数据页层面的实现等等,这部分知识点还是比较散乱的,需要定期温故。



头信息

不同行格式的记录头信息大同小异,以compact行格式为例,在compact行格式,每条记录的记录头信息占用5个字节共计40个二进制位。如下:


delete_mask:占用1个二进制,有0和1两个值,0表示该记录未被删除,1表示该记录已被删除。考虑到记录重新排列会对性能有影响,记录被删除后不会立即从磁盘上移除,而只是将delete_mask位置1。所有被删除的记录会组成一个垃圾链表,后期如果有新记录插入的时候,可对这些删除的记录占用的空间进行重用。

mini_rec_mask:占用1个二进制,有0和1两个值,1表示该记录是B+树的每层非叶子节点的最小记录。

n_owned:表示当前记录所在的组拥有的记录数。

heap_no:表示当前记录在本页中的位置,该值有两个默认值,0和1,0代表最小记录,1代表最大记录。这两个记录是InnoDB自动插入的,可称为伪记录或虚拟记录。

record_type:表示当前记录的类型,0为普通记录,1为B+树非叶子节点记录,2为最小记录,3为最大记录。

next_record:表示从当前记录的真实数据到下一条记录的真实数据的地址偏移量。



记录增删

mysql中对记录进行操作时涉及到的记录中的头信息字段有delete_mask,next_record,n_owned值,以删除记录为例:

如上,假如该组有四条记录,现在要删除第三条记录,会发生如下变化:

1)将第三条记录的delete_mask值设置为1。

2)将第三条记录的next_record值修改为0。

3)将第二条记录的next_record值指向第四条记录。

4)修改该组记录的最大记录的n_owned值减1,即从4变为3。


在这里,第三条记录所占的存储空间并没有被回收,这里就涉及到记录删除空间回收的一些知识点了:

可参考如下:

这里Y表示立刻释放空间,N表示不会立刻释放空间,当数据页中存在多条被删除的记录时,记录的next_record属性会将这些被删除的记录组成一个垃圾链表,然后这部分未立刻释放的空间可以在下次插入记录时进行重用。这也正好解释了为什么有时候你delete大量数据后发现空间并没有释放的场景。当然,你也可以通过执行optimize table xxx命令来立刻释放空间。




数据页

在MySQL中,页是Innodb引擎管理存储空间的基本单位,默认为16kb,针对不同的功能可分为不同的页,而我们通常说的页一般特指数据页,即官方说的存放记录的页,也称之为索引页,数据页按照结构划分可分为7个部分,如下:

这七个部分按照功能来分,又可以分为两类,实际记录和额外信息,除了User Records和Free Space这两部分,其他部分存储的都是额外信息。实际上,页刚开始生成的时候,是没有User Records这一部分的,当新插入一条记录时,会从Free Space部分申请一个记录大小的空间到User Records部分,当不断插入数据后,最终Free Space部分的空间被User Records部分申请完,如果还需要插入新记录,便需要进行申请新的页了。





页目录

之前已经了解过表空间的概念,这里可以先简单了解下Innodb的逻辑存储架构:


按照层级来分的话,也可以这样理解:


页在数据页中是根据主键值从小到大串联成一个单链表的,假设以下场景,某个页中有很多记录,而你要查找的那条记录恰好是靠近单链表的末端,那就只能从最小记录开始沿着链表将该条记录之前的记录都遍历一遍,这会很消耗性能的,同时也会花费较长的时间。因此在Innodb引擎数据页中,会将所有的记录,包括最大和最小记录,但是不包含已删除的记录划分为不同的组,而对于每个分组的记录数也有限制,最小记录所在的分组只能有一条记录,即最小记录本身,最大记录所在的分组拥有的记录数为1~8条,剩下的分组中的记录的条数范围为4~8之间。页目录会记录每个组的最后一个记录的地址偏移量,而这些地址偏移量则被称为槽(slot),因此,页目录是由槽组成的。

初始时一个数据页中只有最小记录和最大记录两条记录,这两条记录分属于不同的组,之后每新增一条记录,则会从页目录中主键值比本记录的主键值大且差值最小的槽,然后将该槽对应的n_owned值增加1,表示该组又添加了一条新的记录。如果某个组内的记录数已经达到8个,此时还需要新增一条记录,则会将该组中的记录进行拆分,一个组中4条记录,一个组中5条记录,并在页目录中新增一个槽来记录新增分组中最大记录的偏移量。


自问自答

Q:
为什么建议表有主键?

在生产上,DBA同学会要求业务同学每张表都建立主键,但是往往业务同学却不在意,从前面的总结中可以看到,如果表有主键,表中的记录在数据页中是根据主键大小进行存储的,在查找某条记录时,可以通过二分法查找页目录中的槽位很快定位到记录所在的分组然后找到记录。而如果表中没有主键,虽然mysql会自动生成一个隐藏字段row_id作为主键,但是row_id的大小是由记录插入先后决定的,此时查找某条记录时可能就需要全表扫描了,如果表的数据量很大,查询性能会很差。

Q:
如何优雅地释放表空间?

前面总结了mysql删除表操作释放空间的时候,讲到了可以通过optimize操作立马释放空间,但是如果删除的记录数较多,例如几十甚至上百万,而表又没有设立主键,这时候可能会导致两个问题:

1).执行时间过长,占用资源

2).引起较大主从延时

这里个人推荐的三种做法是:


方法一:

先在备库执行如下操作:

#查看变量值:

show variables like "%innodb_online%";

#修改全局变量值

set global innodb_online_alter_log_max_size=18446744073709551615(修改为合理值);

#查看变量值:

show variables like "%sql_log_bin%";

#会话级关闭binlog日志记录

set session sql_log_bin=off;

#重建表

alter table xxx engine=innodb;

#查看变量值:

show variables like "%innodb_online%";

#修改全局变量值

set global innodb_online_alter_log_max_size=134217728(修改为原来值);

备库执行完验证主从同步正常后进行主从切换后在原主库执行相同操作。

注:mysql把在ddl时间内的所有的 插入,更新和删除操作记录到一个日志文件, 然后再把这些增量数据应用到相应的表上(等表上的事务完全释放后),这个临时日志文件的上限值由innodb_online_alter_log_max_size指定,详细的可去官网查询。


方法二:

先在备库执行如下操作:

#查看变量值:

show variables like "%sql_log_bin%";

#会话级关闭binlog日志记录

set session sql_log_bin=off;

#表分析

optimize table xxx;

备库执行完验证主从同步正常后进行主从切换后在原主库执行相同操作。


方法三:

先在备库执行如下操作:

#查看变量值:

show variables like "%sql_log_bin%";

#会话级关闭binlog日志记录

set session sql_log_bin=off;

#表修改

alter table xxx force;

#表优化

analyze table xxx;

备库执行完验证主从同步正常后进行主从切换后在原主库执行相同操作。

Q:
数据页中如何查找指定主键值记录?

在一个数据页中根据制定主键值查找记录,可分为以下几步:

1).通过二分法确定该记录所在的槽,虽然每个槽对应的记录都是该组中主键值最大的记录,但是每个槽是相邻的,因此可以找到相邻槽位对应的记录,该记录的下一条记录就是该组中主键值最小的记录。

2).每组内每条记录的next_record字段指向了下一条记录,通过记录的next_record字段可以遍历组内的每条记录,而一个组内最多只能有8条记录,即使遍历整个组也是很快的。


结尾小结

先送上祝福吧,虎年快乐。这段时间偷懒了,原本想着过年假期多学一学,但是由于疫情,过年没回去,加上杭州天天下雨,心情比较差,也没了学习的劲头。前几天偶然看见后台一位同学的留言,很暖心也很鼓励。觉得还是要继续学起来,周末正好有时间,笔记记起来吧。本篇主要是数据页相关的一些知识点,只归纳了部分,余下的部分下一篇继续总结吧。




END



扫码关注我
每天进步一点点,未来才可期。如果你也渴望成长,可以添加微信xuwl_1234,我们一起学习,一起探讨。
赞一下你最美!

原文作者:DBA修行之路;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2021-05-25

  • 博文量
    64
  • 访问量
    23946