数据库记录在磁盘中的存储

首先,一条数据库记录会有一个header, 存储本记录的长度,并包含一个指向table schema的指针。如果记录里中包含不定长字段(如varchar),则在header中还应存储这些不定长字段的offset和实际长度.

典型情况下,一个block可以存储一个以上记录(下面会提到记录过大的情况). 为了记录每条记录在block内部的offset,可以在block header存放这些信息(当然,不是一定要放在header里)。各条记录的offset目录称作offset table.

这时,一条记录的地址 = block的物理地址 + 记录在block中的offset

插入记录时,如果记录顺序不重要,则直接插入一个block的空闲处或另找一个新block>,并更新offset table. 如果记录顺序重要,则找到应该放置此记录的block, 插入记录,并在必要的情况下滑动block内部分记录以保持顺序;如果当前block内的空闲空间不足,先插入,再把溢出的其他记录放到下一个block中,或者专门分配一个新block来存放,这个新block称为overflow bock, 当前block的header中会有一个指针指向它。

删除记录时,可以滑动块内的部分记录,填补空白以节省空间。那么原先指向本记录的指针,是不是就会指向新入驻的记录? 为了避免这种情况下,删除记录后应该将offset table中的相应表项处设置一个tombstone, 指向本记录的指针发现记录指向了tombstone, 就知道记录已被删除。

修改记录时,如果记录是定长的,则直接修改,不需要额外动作; 否则,就要像增删一样考虑新记录过长和以及新记录变短时填补空白的问题。

p.s. 如果记录太大,则可能需要跨block存放(spanned record).  这时一条记录在N个block中各有一个fragment. 在这种记录下,记录的header中需要标识自己是一条完整的记录,还只是一个fragment; 如果是fragment, 还需要存储指向下一个fragment或其他fragment的指针

Leave a Comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.