MySQL存储引擎
>>
讨论MySQL中主要的几个存储引擎,复杂的不同处理细节,无法做到每个存储引擎都细化。
仅是提供代码中的核心部分指引。
>>不同存储引擎的特性
事务支持: InnoDB、NDB
索引支持:
MyISAM(B-tree、R-tree、full text)
InnoDB(B-tree)
NDB(Hash、B-tree)
缓存:
MyISAM(缓存索引)
InnoDB(缓存索引与数据)
NDB(缓存索引)
锁:
MyISAM(table)
InnoDB(row)
NDB(row)
仅有InnoDB支持外键
>>结构的相同之处
不同存储引擎的实现存在巨大的不同,但所有的存储引擎都需要集成到MySQL服务层。从这个层面上讲,不同的存储引擎有类似的处理代码。不考虑支持一些基本的操作如表相关的记录、列、索引,读写操作,以及其他根据存储引擎交互接口规范而定的需求。存储引擎继承方式实现table管理代码提供的函数和属性。
与存储引擎无关,所有的表都有.frm文件来定义表结构,如名字、类型、长度、索引信息等
.frm文件本质存储的信息是由CREATE TABLE指定的。
5.1版本之前,.frm文件名与表名相同,存放在数据库名的文件夹中。
之后版本有所更新,表和数据库名字由build_table_filename()(sql/sql_table.cc)编码指定.
读取与解析.frm文件在openfrm()(sql/table.cc)中,创建在create_frm()中实现。
MySQL服务层读取.frm文件后,将信息保存在table缓存中,下次如果需要访问表结构则直接从缓存里读取。
MySQL服务层使用表锁机制。存储引擎可以利用这个特性或者绕过服务层的表锁机制让其总是赋予写锁权限,如果赋予总是赋予写锁权限,那么存储引擎有责任自己确保并发处理时数据的一致性。
>>MyISAM
MySQL首次发布时,并没有所谓的抽象层,对于想对MySQL扩展非常不易,那时候的MyISAM还叫ISAM。后续抽象层的重构,ISAM改名为MyISAM。
MyISAM结构
>>
讨论MySQL中主要的几个存储引擎,复杂的不同处理细节,无法做到每个存储引擎都细化。
仅是提供代码中的核心部分指引。
>>不同存储引擎的特性
事务支持: InnoDB、NDB
索引支持:
MyISAM(B-tree、R-tree、full text)
InnoDB(B-tree)
NDB(Hash、B-tree)
缓存:
MyISAM(缓存索引)
InnoDB(缓存索引与数据)
NDB(缓存索引)
锁:
MyISAM(table)
InnoDB(row)
NDB(row)
仅有InnoDB支持外键
>>结构的相同之处
不同存储引擎的实现存在巨大的不同,但所有的存储引擎都需要集成到MySQL服务层。从这个层面上讲,不同的存储引擎有类似的处理代码。不考虑支持一些基本的操作如表相关的记录、列、索引,读写操作,以及其他根据存储引擎交互接口规范而定的需求。存储引擎继承方式实现table管理代码提供的函数和属性。
与存储引擎无关,所有的表都有.frm文件来定义表结构,如名字、类型、长度、索引信息等
.frm文件本质存储的信息是由CREATE TABLE指定的。
5.1版本之前,.frm文件名与表名相同,存放在数据库名的文件夹中。
之后版本有所更新,表和数据库名字由build_table_filename()(sql/sql_table.cc)编码指定.
读取与解析.frm文件在openfrm()(sql/table.cc)中,创建在create_frm()中实现。
MySQL服务层读取.frm文件后,将信息保存在table缓存中,下次如果需要访问表结构则直接从缓存里读取。
MySQL服务层使用表锁机制。存储引擎可以利用这个特性或者绕过服务层的表锁机制让其总是赋予写锁权限,如果赋予总是赋予写锁权限,那么存储引擎有责任自己确保并发处理时数据的一致性。
>>MyISAM
MySQL首次发布时,并没有所谓的抽象层,对于想对MySQL扩展非常不易,那时候的MyISAM还叫ISAM。后续抽象层的重构,ISAM改名为MyISAM。
MyISAM结构
表格式定义:通用的.frm文件
数据存储:数据文件(.MYD)与索引文件(.MYI)
>> 数据文件
带有必要元数据的表记录的简单格式。两种记录格式:固定长度格式和变长格式
数据存储:数据文件(.MYD)与索引文件(.MYI)
>> 数据文件
带有必要元数据的表记录的简单格式。两种记录格式:固定长度格式和变长格式
*固定长度:
如果没有包含bit类型的列时,记录头长度通过(8+n)/8计算而来,n代表列数目。记录头第一个位标识该记录是否被删除,随后每个位标识可空列是否为空标志,剩余bit没有使用。
如果包含了bit类型的列时(5.0.3+),会将bit类型的长度对8圆整之后的余数存入到记录头,如bit(19),会将19%8=3bit存在记录头中
如果包含了bit类型的列时(5.0.3+),会将bit类型的长度对8圆整之后的余数存入到记录头,如bit(19),会将19%8=3bit存在记录头中
如果标识行已经被删除,则接下来的尾数用于指向下一个已经被删除的记录位置,这样子将删除记录链表式存储,插入操作可以覆盖在已经被删除的记录位置,无需追加在文件尾端。
跟着记录头之后便是按照顺序记录了列数据。整型与浮点类型数据按照小端形式存储。
固定长度相关的代码实现: storage/myisam/mi_statrec.c
固定长度相关的代码实现: storage/myisam/mi_statrec.c
*变长记录:
行开头记录标志位图,指示某列为空或者为0,如果列为空或者为0情况,那该列除了在位图中占用空间外,不需要其他空间。
变长字段的存储使用长度+数据保存,所以需要占用空间多了一个长度位。
行变长可能导致行分片实现,如果插入的位置不够存放时。
反之,也可能产生碎片。
需要optimize table或myisamchk
定义实现于 storage/myisam/mi_dynrec.c
>> 索引文件
索引文件头由不同的节组成:state、base、keydef、recinfo。
state和base节各仅有一个; 每个索引都有keydef节对应; 组合索引中的每个列都有recinfo节。
定义实现于 storage/myisam/mi_dynrec.c
>> 索引文件
索引文件头由不同的节组成:state、base、keydef、recinfo。
state和base节各仅有一个; 每个索引都有keydef节对应; 组合索引中的每个列都有recinfo节。
state节通过storage/myisam/mi_open.c文件的mi_state_info_write()写和mi_state_info_read()读,包含数据文件长度、时间戳,表打开次数、索引个数、删除和存在的记录数、每个索引的root指针以及很多其他参数。
对应的结构体是MI_STATE_INFO,定义在storage/myisam/myisamdef.h
base节紧随state节之后。保存表中记录数,列个数,各种限制值(如最大索引长度或者最大索引块)以及其他一些信息。
base节为访问表的所有线程所共享,每一个线程使用一份独立的base拷贝数据。
base节通过storage/myisam/mi_open.c的mi_base_info_write()写和my_n_base_info_read()读,对应的结构体是MI_BASE_INFO,定义在storage/myisam/myisamdef.h
base节之后,跟着多个keydef节,每个索引对应一个keydef节。每个keydef节开头包含了索引组成个数、索引类型、特殊标志、索引使用的索引页、索引长度限制。 索引对应包含一个或者多个列,每个列在索引文件中对应一个keyseg节,每个keyseg节中包含索引组成部分的信息。keydef节通过storage/myisam/mi_open.c的mi_keydef_write()和mi_keydef_read()实现读写。对应结构体MI_KEYDEF,定义在storage/myisam/myisamdef.h
recinfo节跟在keydef节后。每个recinfo由列类型编码,列长度,表示列数据是否为空的标志组成。通过myisam/mi_open.c的mi_recinfo_write()和bymi_recinfo_read()实现读写,对应结构体是MI_COLUMNDEF,定义在include/myisam.h
最后接着是索引页,构成B-TREE或者R-TREE的节点。
最后接着是索引页,构成B-TREE或者R-TREE的节点。
每个索引页有两个字节的头,第一个bit用来表示是否叶子结点,剩下的表示索引页的使用长度。
>>MyISAM 索引类型
>>MyISAM 索引类型
B-tree索引
相关代码storage/myisam文件夹中的mi_key.c/mi_search.c/mi_write.c/mi_delete.c
B-tree页长度可以通 过变量myisam_block_size来设定,通过第一bit区分是不是叶子结点
叶子与非叶子结点都包含了key值和指向datafile中的记录位置,非叶子结点另外还需指向子节点。
B-tree页长度可以通 过变量myisam_block_size来设定,通过第一bit区分是不是叶子结点
叶子与非叶子结点都包含了key值和指向datafile中的记录位置,非叶子结点另外还需指向子节点。
全文索引
本质上是B-tree。保存了相关的记录指针以及索引列中每个词的权重值。
工具myisam_ftdump分析全文索引信息
如myisam_ftdump -d /var/lib/mysql/test/t1 1
最后参数表示key的序号。如何计算序号,show create table,计算索引的顺序值-1便是key序号
插入时分析记录的全文索引列(storage/myisam/ft_parser.c),提取keyword序列,忽略低选择度的词语(storage/myisam/ft_stopwords.c和storage/myisam/ft_static.c),计算keyword频度,计算每个keyword的权重,得到<keyword,权重值,record指针>,然后插入到B-TREE全文索引树中(storage/myisam/ft_update.c)
查找时,实际是对全文索引树的查找。根据keyword来查找,得出相关的记录,根据权重排序,返回结果。
>> InnoDB
事务支持
MVCC
行锁支持
外键
死锁检测
快速故障恢复
表空间概念
共享空间或者每个表一个空间
聚簇索引存储方式, B-tree代码实现于innobase/btr/btr0btr.c
聚簇索引和第二索引都是存储在硬盘,当缓存索引页时,InnoDB使用自适应hash索引加速缓存页查找。自适应hash索引缓存实现storage/innobase/ha/ha0ha.c
MyISAM仅是缓存索引页,InnoDB缓存索引与数据。
不依赖操作系统缓存系统,避免系统调用。
操作系统双缓存开启,不使用浪费了内存。
InnoDB存在变量innodb_flush_method,设定为O_DIRECT来关闭系统缓存。
索引缓存的实现代码在storage/innobase/buf/buf0buf.c
InnoDB存在两种类型日志:undo日志和redo日志
undo:用于回滚事务(storage/innobase/log/log0log.c)
redo:用于崩溃恢复信息保存(storage/innobase/log/log0recv.c)
InnoDB两种行格式: storage/innobase/rem/rem0rec.c
page目录: 页内搜索记录,二分查找。storage/innobase/page/page0page.c
InnoDB行数据带有格外两个域:异常恢复信息和多版本信息
异常恢复信息:最后修改该行的事务ID、指向undo日志中回滚段的记录,从undo中可以回滚事务或者获取旧版本数据。
工具myisam_ftdump分析全文索引信息
如myisam_ftdump -d /var/lib/mysql/test/t1 1
最后参数表示key的序号。如何计算序号,show create table,计算索引的顺序值-1便是key序号
插入时分析记录的全文索引列(storage/myisam/ft_parser.c),提取keyword序列,忽略低选择度的词语(storage/myisam/ft_stopwords.c和storage/myisam/ft_static.c),计算keyword频度,计算每个keyword的权重,得到<keyword,权重值,record指针>,然后插入到B-TREE全文索引树中(storage/myisam/ft_update.c)
查找时,实际是对全文索引树的查找。根据keyword来查找,得出相关的记录,根据权重排序,返回结果。
>> InnoDB
事务支持
MVCC
行锁支持
外键
死锁检测
快速故障恢复
表空间概念
共享空间或者每个表一个空间
聚簇索引存储方式, B-tree代码实现于innobase/btr/btr0btr.c
聚簇索引和第二索引都是存储在硬盘,当缓存索引页时,InnoDB使用自适应hash索引加速缓存页查找。自适应hash索引缓存实现storage/innobase/ha/ha0ha.c
MyISAM仅是缓存索引页,InnoDB缓存索引与数据。
不依赖操作系统缓存系统,避免系统调用。
操作系统双缓存开启,不使用浪费了内存。
InnoDB存在变量innodb_flush_method,设定为O_DIRECT来关闭系统缓存。
索引缓存的实现代码在storage/innobase/buf/buf0buf.c
InnoDB存在两种类型日志:undo日志和redo日志
undo:用于回滚事务(storage/innobase/log/log0log.c)
redo:用于崩溃恢复信息保存(storage/innobase/log/log0recv.c)
InnoDB两种行格式: storage/innobase/rem/rem0rec.c
page目录: 页内搜索记录,二分查找。storage/innobase/page/page0page.c
InnoDB行数据带有格外两个域:异常恢复信息和多版本信息
异常恢复信息:最后修改该行的事务ID、指向undo日志中回滚段的记录,从undo中可以回滚事务或者获取旧版本数据。