前言

我们这里来看一下 MyISAM 存储引擎, 我们常见的那些 user, db, table_priv, proc 等等是基于 MyISAM

这是我们经常会提及的 两种持久化的存储引擎之一, 一是 MyISAM存储引擎, 另外一个是 InnoDB存储引擎 

我们这里来看一下 MyISAM 中固定长度的数据表的相关处理 

 

mysql. tables_priv 的表结构创建如下 

CREATE TABLE `tables_priv` (
  `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '',
  `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
  `User` char(32) COLLATE utf8_bin NOT NULL DEFAULT '',
  `Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
  `Grantor` char(93) COLLATE utf8_bin NOT NULL DEFAULT '',
  `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') CHARACTER SET utf8 NOT NULL DEFAULT '',
  `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '',
  PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`),
  KEY `Grantor` (`Grantor`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Table privileges'

 

 

基于 固定长度MyISAM 的数据表的数据输出 

执行 “select * from tables_priv where Table_name = 'tz_test';”

外层读取的时候 mi_read_rnd_static_record 传入的偏移为 info->nextpos

然后接下来的 mi_read_rnd_static_record 中进行迭代的时候 更新了 info->nextpos

60 mysql 存储引擎之静态格式 MyISAM_数据

 

对于固定长度的 MyISAM 的数据表, 迭代 info->nextpos 的方式如下 

是直接增量量更新, 因为记录的长度是固定的, 因此增加这个固定的长度即可 

然后 这里是 使用缓存的读取, 没有缓存的读取, 就是直接读取 MyISAM 表的数据文件 

60 mysql 存储引擎之静态格式 MyISAM_存储引擎_02

 

读取的迭代处理如下, 这里使用的 READ_CACHE_USED, 这里的使用更倾向于作用为 BUFFER 

第一次读取填充 可读取的字节序列[min(文件大小, buffer的可写空间)] 到 buffer 

然后 后面的再缓冲空间能够提供数据的时候, 直接拷贝缓冲空间的数据, 缓冲空间不够了, 再进行读取 

60 mysql 存储引擎之静态格式 MyISAM_MyISAM_03

 

第一次读取的时候, 读取了 max_length 2841 个字节的数据到 buffer

max_length 的计算是取自 文件大小 和 buff可写空间 的较小值

然后后面第二次, 第三次读取就是从 这个 buffer 中拷贝数据到 上层 buf 中了 

这里的读取是 seek + read 来实现读取 目标偏移 的 max_length 个字节 

60 mysql 存储引擎之静态格式 MyISAM_数据_04

 

第二条记录的读取, 可以看到当前 偏移是 947, 也就是 第二条记录的开始

然后此时 因为 buffer 中已经读取了 2841, 然后 可以直接使用 buffer 的数据 

这里是直接使用的 memcpy 拷贝, “memcpy(Buffer, info->read_pos, Count)”

第三条记录的读取, 同样 

60 mysql 存储引擎之静态格式 MyISAM_fixed_05

 

假设是 READ_CACHED_USED 为 false 的场景下

是直接使用 pread, 来实现的 携带偏移 的读取, 偏移为 0, 读取长度为 947, 一条记录的数据 

和 READ_CACHED_USED 的差距 一眼就能看出来了吧, 是否使用了 buffer

60 mysql 存储引擎之静态格式 MyISAM_mysql_06

 

 

基于 固定长度MyISAM 的数据表的数据行  

数据行 的信息如下

60 mysql 存储引擎之静态格式 MyISAM_fixed_07

 

 

基于 固定长度MyISAM 的数据表的数据录入  

执行 sql 如下, 在 mysql.tables_priv 中增加一条记录, 我们来看一下 这个过程

create user 'tz_test_001'@'%' identified by 'tz_test';
grant select on test_02.tz_test_02 to 'tz_test_001'@'%';
drop user 'tz_test_001';

 如果没有将新增的数据放到最后的需求, 则将数据替换删除记录 

60 mysql 存储引擎之静态格式 MyISAM_mysql_08

 

否则是 带缓冲的写, 或者 直接写出数据到 MyISAM 的数据表的数据文件[通过 pwrite]  

60 mysql 存储引擎之静态格式 MyISAM_mysql_09

 

 

 基于 固定长度MyISAM 的数据表的数据删除

执行 sql 如下, 在 mysql.tables_priv 中删除一条记录, 我们来看一下 这个过程

create user 'tz_test_001'@'%' identified by 'tz_test';
grant select on test_02.tz_test_02 to 'tz_test_001'@'%';
drop user 'tz_test_001';

记录的删除处理如下, 将原来该记录的数据覆盖为 标记删除 + 下一个删除记录的索引, 总共 7 字节 

然后 info->s->state.dellink 可以构成一个已经删除的元素的链表 

根据 info->lastpos 可以知道, 我们这里删除的是 第四条记录

60 mysql 存储引擎之静态格式 MyISAM_数据_10