前言
我们这里来看一下 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
对于固定长度的 MyISAM 的数据表, 迭代 info->nextpos 的方式如下
是直接增量量更新, 因为记录的长度是固定的, 因此增加这个固定的长度即可
然后 这里是 使用缓存的读取, 没有缓存的读取, 就是直接读取 MyISAM 表的数据文件
读取的迭代处理如下, 这里使用的 READ_CACHE_USED, 这里的使用更倾向于作用为 BUFFER
第一次读取填充 可读取的字节序列[min(文件大小, buffer的可写空间)] 到 buffer
然后 后面的再缓冲空间能够提供数据的时候, 直接拷贝缓冲空间的数据, 缓冲空间不够了, 再进行读取
第一次读取的时候, 读取了 max_length 2841 个字节的数据到 buffer
max_length 的计算是取自 文件大小 和 buff可写空间 的较小值
然后后面第二次, 第三次读取就是从 这个 buffer 中拷贝数据到 上层 buf 中了
这里的读取是 seek + read 来实现读取 目标偏移 的 max_length 个字节
第二条记录的读取, 可以看到当前 偏移是 947, 也就是 第二条记录的开始
然后此时 因为 buffer 中已经读取了 2841, 然后 可以直接使用 buffer 的数据
这里是直接使用的 memcpy 拷贝, “memcpy(Buffer, info->read_pos, Count)”
第三条记录的读取, 同样
假设是 READ_CACHED_USED 为 false 的场景下
是直接使用 pread, 来实现的 携带偏移 的读取, 偏移为 0, 读取长度为 947, 一条记录的数据
和 READ_CACHED_USED 的差距 一眼就能看出来了吧, 是否使用了 buffer
基于 固定长度的MyISAM 的数据表的数据行
数据行 的信息如下
基于 固定长度的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';
如果没有将新增的数据放到最后的需求, 则将数据替换删除记录
否则是 带缓冲的写, 或者 直接写出数据到 MyISAM 的数据表的数据文件[通过 pwrite]
基于 固定长度的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 可以知道, 我们这里删除的是 第四条记录
完