csv存储引擎是mysql自带的一种简单的存储引擎,可以直接处理CSV文件。
该存储引擎特点:
1.所有的列不能为NULL
2.不支持索引
3.不支持分区表
4.该存储引擎的数据文件是普通的csv文件,可以直接拷贝出来使用或编辑。
该存储引擎工作原理:
1.该存储引擎每个表有一个元数据文件,文件名:表名.CSM。格式如下:
offset |
长度 |
取值 |
0 |
1 |
254.用于检测文件是否被损坏 |
1 |
1 |
csv文件的version,当前取值为1 |
2 |
8 |
csv数据文件的记录数 |
10 |
8 |
checkpoint,保留值,目前未使用 |
18 |
8 |
autoincrement,保留值,目前未使用 |
26 |
8 |
auto_flush_fields,保留值,目前未使用 |
34 |
1 |
0:没有损害 1:损坏.在修改文件时会先将该标记保存为1,修改成功后修改为0 |
2.insert记录:直接在文件末尾添加记录。
3.delete记录:统计要删除的记录,然后新建一个文件,将原文件中没有删除的记录拷贝到新文件中,重命名新文件替代原文件。因此delete效率低下。
4.update记录:将update的记录拆分为dellete和insert两个操作,先在原文件中统计要更新的记录,将这些记录标记为删除,新建一个文件,将要更新后的记录添加到新文件中,处理完成后再将原文件中所有的没有标记为删除的记录迁到新文件中,重命名新文件替代原文件。因此update效率低下。
5.mysql通用日志表mysql.general_log和慢查询日志表mysql.slow_log默认采用CSV存储引擎,在该存储引擎中标记为log table,log table不支持update和delete操作。
6.check操作:读取数据文件中的每行记录,如果文件内容没有问题,并且文件中的记录等于缓存中的记录数,则check正确。
7.repair操作:按行读取文件,碰到第一个出问题的记录(可能是记录格式等原因导致),将该记录之前的记录拷贝到新文件,重命名新文件替代旧文件。因此会导致错误行之后的记录丢失。
源码解析:
Transparent_file:负责读取文件中的内容。该结构为了提高读取文件的效率,在内部有一个缓存buff,长度为4K,即每次读文件读取4k大小的内容。
lower_bound和upper_bound分别对应buff缓存读取的内容在数据文件中的偏移量。
st_tina_share: 该表共享信息,存储在一个HASH对象中,key是表名。
该结构 主要内容:表名、数据文件名、记录数、是否崩溃标记、元数据文件对象、数据文件的长度、数据文件的对象
主要数据成员:
use_count:该结构当前正在被使用的次数,get_share中值+1,free_share中值-1
update_file_opened:在update和delete操作中创建的新文件成为update_file
saved_data_file_length:数据文件的长度,在读文件的时候用到。防止和并行插入的记录行发生冲突。
crashed:标记元数据文件是否损坏
data_file_version:在update和delete操作后用update_file替换数据文件,会导致该值+1.通知其他对象数据文件发生改变,可能要重新打开数文件。
ha_tina:存储引擎的主要接口,负责处理增删改查、check、repair等操作。具体的操作原理上文已经详细描述过。这里挑部分重要内容讲解。
主要数据成员:
current_position和next_position:该表在处理过程中是逐行扫描处理(调用rnd_next)。current_position是当前行的开头,next_position 是下一行的开头。next_position在find_current_row函数中进行更新。
chain_buffer[DEFAULT_CHAIN_LENGTH]、chain、chain_ptr、chain_alloced、chain_size:CSV存储引擎删除记录时,会先将要删除的记录标记起来,就是通过chain结构标记的,该结构中每个成员对应了一个要删除数据端的开始偏移量和结束偏移量,在rnd_end 函数中根据清理数据。chain指向chain结构的起始位置、chain_ptr指向china结构的终止位置。china结构最初指向chain_buffer,此时chain_alloced=0,当chain_buffer空间不足,会重新分配空间指向chain,此时设置chain_alloced=1.chain_size表示chain结构中分配的数据空间
主要函数:
find_current_row:根据current_position的内容读取一行记录,更新next_position的值
rnd_next:读取当前行的记录
rnd_end:每次全表扫描之后调用.将数据文件中有效的内容写入到update_file,然后重命名文件。
position函数:如果需要执行order by排序,在每次rnd_next之后会调用postiion,将记录的键值存储到一个字节数组中。
rnd_pos:根据position函数存储的位置信息获取一行记录
get_write_pos:获取下一个写地址,如果file_buff中有chain,返回chain的begin地址,否则返回file_buff的结尾。