InnoDB硬核游记[施工中]

缓冲池
* InnoDB基于磁盘存储,其中的记录按页的方式来管理,为了提升IO须要内存上开辟缓冲池
* 大小可经过innodb_buffer_pool_size确认
* 磁盘读取页时会先放在缓冲池,用于下一次的缓存命中
* 修改页先修改缓冲池中的页,再以必定的频率将脏页刷新到磁盘中(经过checkPoint机制确认频率)
* 缓冲池中的支持的缓存类型有:
* 索引页
* 数据页(InnoDB中和索引页是同一个东西)
* undo页
* Insert Buffer
* 自适应哈希索引AHI
* lock info
* data dictionary
* 缓冲池不止一个
* 缓冲池的管理算法

* 经过变种(midpoint)的LRU来进行淘汰
    * 默认页的大小16KB
    * 新读取的页被放入midpoint位置(5/8),midpoint后成为old列表,前称为new列表
    * new尽可能长是为了防止部分SQL操做访问过多的页使得热点数据淘汰过快

checkPoint机制
* 用于刷新实例中的脏页到硬盘的机制缓存

Insert Buffer
* 和数据页一致,也是物理页的一部分,用于提升二级索引(非惟一)的插入性能
* 就是把屡次插入放入buffer中,等到足够的时机合并成一个索引页再插入B+树,减小离散性带来的IO问题
* 因为惟一索引须要查找索引页来判断惟一性,所以不能使用
* 数据结构上是一棵B+树,全表只有一棵来负责这个Buffer,存放于共享表空间
* 页由(space,[marker,]offset)惟一肯定(非叶节点),安全

* marker仅用于兼容性保证
    * space id用于确认表的位置
    * offset表示页所在的偏移
* 叶子节点还多了metadata字段,内部包含有

    * IBUF_REC_OFFSET_COUNT,用于排序每一个记录进入Insert Buffer的顺序
    * IBUF_REC_OFFSET_TYPE
    * IBUF_REC_OFFSET_FLAGS
* 叶子节点第五列即是记录实际插入的各个字段

Change Buffer
* 更普遍的支持Insert Delete Update缓冲(分别为Insert Buffer / Delete Buffer / Purge Buffer)
* UPDATE操做的步骤:1.记录标为已删除,2.真正将记录删除数据结构

double write机制
* 提供高于物理层面的高可用机制,在应用redo log前须要一个页的副本,当写入失效时,先经过副本还原页,再进行redo,从而避免了页损坏的问题异步

自适应哈希索引性能

* AHI根据缓存池B+树上的热点数据来创建哈希索引
    * 创建依据:按照同一索引的相同查询方式访问100次 且 访问N >= 页中记录 / 16 次

AIO
* AIO可以让IO请求连续发出,无需等待,提升IO能力
* InnoDB的AIO还会进行IO合并,内部会经过(space,offset)将可能合并的IO一并操做
* read ahead / 脏页刷新 / 磁盘写入均由AIO完成spa

杂乱笔记
* 插入聚簇索引是顺序的,不须要磁盘的随机读取
* 插入非聚簇索引(且非惟一)时经过Insert Buffer提升IO性能
* MyISAM的缓冲池只缓存索引文件,不缓存数据文件
* 没有主键会优先选取UNIQUE NOT NULL做为主键,没有再自行建立(多个则挑第一个定义的)线程

表的结构
* 全部数据存放于表空间
* 表空间由段(区(页))组成
* 段有数据段和索引段之分(还有回滚段),但InnoDB是索引组织表形式,二者是等同的,索引即数据
* 区是连续的页,一次申请4-5个区,每一个区有64个连续页(1个区16KB
* 页是InnoDB磁盘管理最小单位,可经过innodb_page_size设置4K/8K/16K
* 数据页(B-TREE NODE)存放实际的行数据code

UNIQUE NOT NULL 和 PRIMARY区别
* 查询避免不了从新往PRIMARY树再查询一遍(覆盖索引除外)
* 相比事务依然可享受降级为RECORD LOCK的待遇排序

全文索引
* InnoDB已经支持全文索引了
* 内部采用倒排索引机制,记录(word,(columID,idx)...(多个))来快速查找(为啥叫倒排,由于是根据value来找key)

关于幻读
* 牛逼的InnoDB已经在repeatable read把幻读解决了
* 具体是经过next-key lock机制
* 惟一性肯定时还经过锁降级为record lock来进一步加快速度
* 要想显式关闭gap lock至少要将为read commited

脏页和脏数据
* 忽然感受没差。。
* 脏页是异步产生的,且保证最终一致性
* 脏数据是特指事务未提交的数据,一致性没法保证


* 锁分为面向事务的lock和面向线程的latch
* lock分为行锁、表锁、意向锁
* latch分为mutex、rwlock
* 前者存在于Lock Manager的哈希表中,后者存在每一个数据结构中
* 前者经过图判环、timeout机制检测死锁、后者无死锁检测,仅用于保证线程安全

行级锁
* S Lock:容许事务读取一行数据
* X Lock:容许事务删除/更新一行数据
* 对于S锁和X锁,只有SS是兼容的,其余组合不兼容(对于同一行而言)

意向锁(透明)
* InnoDB中意向锁就是表级锁,意味请求事务获取表中某几行的锁
* IS Lock:共享锁
* IX Lock:排他锁
* 意向锁不阻塞除全表扫描外任何请求,我的感受就是个简单标记

锁的兼容性
* S锁:对IS和S兼容
* X锁:所有不兼容
* IS锁:IS IX S兼容
* IX锁:IS IX兼容(要写入的行的安全性已经由X锁保证,快速排除掉S锁)

MVCC的使用时机?
* READ COMMITED / REPEATED READ使用一致性非锁定读(生成快照,无需等待X锁。。。)
* READ COMMITED老是读取锁定行最新版本
* REPEATABLE READ老是读取事务开始的版本

行锁算法
* record lock:解决锁定单个行
* gap lock:解决锁定范围行,阻止多个事务插入同一范围
* next-key lock:前两种机制mix,解决幻读

* 具体的会锁定(-inf,a_1] (a_1,a_2] (a_2,a_3] (a_3,inf),当事务在该范围内再插入一个key,锁会从新划分该部分
    * 具备锁降级机制,当切仅当使用具备惟一性的索引且操做单个行时,next-key降级为record
    * 为何不直接用gap lock解决幻读?我以为是没问题的只是InnoDB实现上混合了record lock机制,在控制的粒度上更细腻(分段锁总比全局锁好)

Question * 缓冲池 - OK * 索引到底存储在哪 - OK * 我的认为数据页和索引页都在磁盘,可是缓冲池机制会把访问到的临时放在内存上经过LRU管理,可是索引的根会常驻内存以快速找到磁盘索引的入口 * 索引和普通字段的存储区别 - OK *

相关文章
相关标签/搜索