mysql
插入连续的数据在一个页里,每次查询都有一次与磁盘的io,比较耗时,而我们拿数据是从内存中拿,为了减少磁盘与内存的交互,innodb采取页的方式存储数据
表空间 磁盘上文件的一个映射,定义数据位置信息的一块空间
infimum 存在表中的任意数据都没有我小 supermum 存在表中的任意数据都没有我大
从free space中申请空间,free space越来越小,user records越来越大,最后数据满了,free space没有空间了
表中没有主键也没有唯一约束的时候,roow_id可以保证一条数据的唯一性
记录:存储在页中插入的一条数据
看到这里,大家可能会有疑问:我删除了一条记录,难道它还存在于页中吗,或者说还是存放在磁盘上吗?答案是:没有被删除,也还存放磁盘上。因为当删除记录时,存储引擎是不会立即删除它们的,因为移除它们之后,还需要把其它的记录重新排列,这样就会造成性能损耗,所以只是打上删除标签而已。当然了,都把这些记录打上删除的标签了,肯定不能和那些正常记录在一个链表中了,就会形成一个所谓的垃圾链表,在这个链表中的记录占用的空间称之为所谓的可重用空间,之后如果有新记录插入到表中的话,可能把这些被删除的记录占用的存储空间覆盖掉。
删除操作:deleted_flag置为1,next_record指向下下一条的记录,n_owned条数减1 如果插入一条删除的记录,在垃圾链表的空间没有被覆盖的情况下,插入的顺序也是deleted_flag --0 next_record--下一条记录 n_owned---+1
如果是单页,可以先用二分法找到对应的槽,在遍历next_record
type_record 为1 非叶子节点的目录项 非叶子节点:主键和页号
可以通过回表查找数据,先通过二级索引找到主键,再找到具体的数据 叶子结点由c2+c1组成 非叶子节点 由c2+page组成
控制页:存储了控制缓存页的参数
innodb_buffer_pool_size 默认buffer pool是128M 多出的50%是存控制块的
哈希表:key:表空间+页号
value:控制块 ,由控制块控制缓存页的状态,是否被修改,是否需要同步
将被修改的脏页放到flush链表中,在某一时刻刷新到磁盘
不会出现控制块同时在free链表和flush链表的情况,flush链表的缓存页一定有数据,free链表的缓存页没有
如果buffer pool没有页,从磁盘中加载到lru链表的头部,如果链表中有页,就把这个页放到lru链表的头部
预读 读取当前请求的时候,innodb会默认后面读取的页面也在这个请求的附近,就会提前将后面的那些请求提前读取出来 线性预读 如果顺序访问了某个区(共64个页面)的页面(超过56个页面)就会把下一个区的所有页面全部加载进来 随机预读 没有顺序的去读,如果这个区有连续的13个页面被加载,就会把这个区的所有页面都加载
解决:innodb在初次从磁盘向bp中加载数据的时候只会往old中加载,那么预读只会加载old中的数据
全表扫描 会把lru链表的所有数据都冲刷掉 一个页16kb,全表扫描一个页的时间在1m内
解决:某一时刻间隔内,第一次全表扫描从old中读取数据与第二次从old中读取数据的时间间隔<1000ms,则数据不会从old刷新到young区
底层以chunk为单位向操作系统申请内存空间