MySQL实现的一点总结(一)

/*********************************
//能写多少算多少吧
//烟花来喽~
*********************************/
Character_set_server:服务器级别字符集
Collation_server:服务器级别比较规则
库级:(不指定则使用上一级的规则)
Create database xx character set gb2312 collate gb2312_chinese_si;
Use xx; show variables like ‘character_set_database’;
表级:
Create table t ( col varchar(10) ) character set utf8 collate utf8_general_ci;
列级:
Alter table t modify col varchar(10) character set gbk collate gbk_chinese_ci;
Character_set_client:服务器认为请求所使用的编码;
Character_set_connection:服务器处理时转化成此编码;
Character_set_results:结果转化成此编码返回客户端;

InnoDB:
将数据分为页,以页(默认16K)为单位在磁盘与内存之间交换
Compact行格式:
变长字段长度表 | null值表 | 记录头 | ( row_id trx_id roll_pointer) | 列值1 | 列值2 | … |(null值不存)
变长字段长度表:存储各(变长字段以及变长编码的定长字段)的真实字节数,列逆序(因为读的时候是从中间往两边走,逆序使得列值和长度对应);如何确定每个字段长度使用一字节还是两字节——先看定义的表结构,if字符数M(如varchar(M))* 每个字符所需的字节数W(根据所使用的字符集)<= 255,则用1字节;否则看真实数据长度,if <= 127,使用1字节,否则使用2字节(这种情况可以字节首位是否为1区分1字节还是2字节)
null值表:每个允许为null值的字段对应1bit,然后补齐为整数字节(高补0)
row_id(6B) trx_id(6B) roll_pointer(7B):这三个由MySQL自动添加,row_id在没有定义主键时添加,trx_id事务ID,roll_pointer回滚指针
列值:定长字段定长编码时按M*N分配存储空间,变长编码时至少占M字节
注意列值这边没有null值(null值由null值表表示)

Redundant行格式:
字段长短偏移表 | 头信息 | 真实数据 …
字段长短偏移表:每个字段的偏移值(结尾的位置),if所有列数据的总长度 <= 127,用1字节表示长度(即每个偏移值占1字节),否则用2字节(>32767时使用溢出页),——why 1字节时是127呢?因为与上面compact不同,这里所有的列都会记录,所以用第一个字节最高位来表示此列是否为null;然后在头信息里边有个1byte_offs_flag表示长度用的1字节还是2字节;另注意此偏移表也包括那三个MySQL自动添加的列
列值:对于变长字符集的定长字段,使用最大长度存储(如utf8字符集使用1~3个字节,则utf8的char(10)分配30字节)

溢出列:(varchar,text,blob都可能溢出)
先搞个溢出:create table xx ( c varchar(65532) ) charset = ASCII row_format = compact;
Insert into xx © values(repeat(‘a’,65532));
格式:字符串前768个 | 溢出页地址(20B)+ 数据字节数
规定一页至少存两条记录,so当 页信息132B + 2 *(额外信息27B + 真实数据nB) < 16384(16K),即n < 8099时不溢出

MySQL5.7默认行格式:dynamic,此格式溢出时将所有真实数据存到溢出页,本页只留那20B地址和字节数

Compressed行格式会进行页面压缩

数据页(索引页):
File header(38B)
Page header (56B)
Infimum + supremum (26B) :页面最小最大记录
User records
Free space
Page directory
File trailer (8B):校验

结合此结构分析一下记录头(位于实际列值和字段长度表之间):
Deleted_flag:1bit,1表示记录已被删除(节约性能,不能真删),所有删掉的形成垃圾链表(可重用空间),可被之后新纪录利用
Min_rec_flag:B+树非叶节点的最小目录项
N_owned:分组后的大哥记录本组记录数,见下
Heap_no:记录在user record中的相对位置
Next_record:到下一条记录真实数据的距离(可正可负,注意是直接定位到真实数据的位置,不是记录的起始位置)——下一条指按主键大小的下一条,即形成单链
由上面的页面结构可知,user records上面是Infimum + supremum——最小最大记录指主键的大小,这俩玩意里边就存了俩单词,并非user插入的记录,相当于user records的头尾指针吧,所以单链类似于:Infimum ——> 主键1 ——> 主键2 ——> … ——> supremum
记录被删后 deleted_flag = 1,next_record = 0,heap_no不变——这里不清楚怎么组织的有效数据链和垃圾链
Page directory(页目录):将所有正常记录分组(包括Infimum和supremum),每组最后一条(主键最大)是大哥,其他是小弟,大哥的n_owned记录组内的记录数,然后将大哥们的真实数据地址(在页面中的偏移量)取出,按序(逆序,从大到小)存入page directory中,每个地址偏移量(slot)占2字节
规定:Infimum的第一组只有一条记录,其余组4~8条,最后一组supremum 1~8条,——即大于8条,就分裂成4+5,并新增一个slot(目录项),修改n_owned等
有了这个目录,页内查找就可以根据slot值进行二分
Page header:记录slot个数,free space地址,记录数,垃圾链表头已删除记录字节数,最后插入位置,插入方向(即新插入的主键比上一条大还是小),正常用户记录数,在B+树中的层级,索引ID等
File header:包含校验和,页号,相邻页号pre和next(页面双链),最后修改的日志号(LSN),页类型,表空间ID
File trailer:校验和(4B),LSN(4B)——这俩跟header里面的是一个东西,头尾比较可以判断数据完整性,是否完整刷新,避免搞一半断电之类的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值