InnoDB总结
2023-04-23 09:42:13 0 举报
AI智能生成
总结Inndb
作者其他创作
大纲/内容
体系架构
后台线程
Master Thread
分类
主循环
刷新循环
后台循环
暂停循环
时间频率
每秒
每十秒
IO Thread
负责IO请求处理
分类
read io thread
write io thread
insert buffer io thread
log io thread
Purge Thread
事务提交后undo log 不需要了,purge thread 负责回收undo 页
原来在master thread 的循环里面做,innodb 1.1 开始拆出了单独的purge thread
可用(innodb_purge_threads=1)控制线程数量
Page Cleaner Thread
1.2x中引入,之前在master thread 中完成脏页刷新,后来讲这个功能放到了单独的线程里面
Innodb 的内存
buffer pool
功能
解决磁盘和cpu之间的性能差异,innnodb 里面的读写都是基于缓冲池的,为了提高并发缓冲池有多个实例
数据类型
索引页
数据页
undo 页
insert buffer
adatptive hash index
lock info
data dictionary
缓冲池管理
buffer pool hit rate
正常应该大于95%,代表缓存命中率,如果小于这个值的话可能是发生了全表扫描
缓冲页链表分类
LRU List
innodb 的lru 实现
插入策略是新数据尾部插入,采用middle point insert strategy 插入
middle point insert strategy
类似jvm年轻待和老年待的思路,将lru list 用middle point 分为
new(老数据,在队列头部) 和 old(新数据,在队列尾部)
然后多次访问统一个缓存页时就会判断缓存页存活是否超过InnoDB_old_blocks_time时间
超过则移入new 区
new(老数据,在队列头部) 和 old(新数据,在队列尾部)
然后多次访问统一个缓存页时就会判断缓存页存活是否超过InnoDB_old_blocks_time时间
超过则移入new 区
Free List
空闲可用的缓存页
Flush List
lru 中的脏页,需要用checkpoint 刷新到磁盘的页
重做日志缓冲(redo log buffer)
功能
缓存redo log,所占空间较小,默认8MB
redo log buffer的刷新时机
Master Thread的每秒循环
事务提交的时候
redo log buffer 剩余空间小于1/2
额外内存池(additional_mem_pool)
innodb 的内存管理和jvm是一致的,缓冲池类似堆的概念,‘额外内存池’则类似于jdb8里面的metaspace,主要负责存储innodb本身的一些数据结构
关键特性
Checkpoint
功能
刷新脏页到磁盘的操作,实现ACID中的Durability
,具体解决的问题的思路:每次刷新多少页到磁盘,每次从哪里取脏页,什么时候触发checkpoint
,具体解决的问题的思路:每次刷新多少页到磁盘,每次从哪里取脏页,什么时候触发checkpoint
checkpoint的必要性
buffer pool 空间有限
redo log buffer 空间有限
什么是LSN(Log Sequence Number)
一个8字节的一直递增的整形数字,表示事务写入redo log 的字节总量,
每个页都有一个LSN 字段,redo log 中有LSN,checkpoint也有LSN
每个页都有一个LSN 字段,redo log 中有LSN,checkpoint也有LSN
checklpoint类型
Sharp Checkpoint
数据库关闭时刷新所有脏页
Fuzy Checkpoint
数据库运行时刷新部分脏页
Fuzzy Check Point 的触发时机
Master Thread Checkpoint
FLUSH_LRU_LIST Checkpoint
LRU List中至少有n个页可用(innodb_Iru_scan_depth=100),该检查放在Page Cleaner Thread 中进行
Async/Sync Flush Checkpoint
重做日志文件不可用用时强制将一些页刷新会磁盘,保证redo log buffer 循环使用
checkpoint_age = redo_lsn - checkpoint_lsn
async_water_mark = 75% * total_redo_log_file_size
sync_water_mark = 90% * total_redo_log_file_size
checkpoint_age<async_water_mark => 不执行checkpoint
async_water_mark<checkpoint_age<sync_water_mark => async checkpoint
checkpoint_age>sync_water_mark => sync checkpoint
async_water_mark = 75% * total_redo_log_file_size
sync_water_mark = 90% * total_redo_log_file_size
checkpoint_age<async_water_mark => 不执行checkpoint
async_water_mark<checkpoint_age<sync_water_mark => async checkpoint
checkpoint_age>sync_water_mark => sync checkpoint
Dirty Page too Much Checkpoint
缓冲池脏页占比超过innodb_max_dirty_pages_pct,强制checkpoint 到磁盘,保证缓冲池有足够可用的页
插入缓冲
Insert Buffer
原理
innodb 按主键索引聚集,主键索引的操作是有序的,一般都是顺序io
,辅助索引(唯一性和非唯一性)叶子节点是主键值
,辅助索引(唯一性和非唯一性)叶子节点是主键值
非唯一性索引更新时的多次随机IO合并为1次,减少非唯一性索引的随机io次数,提高数据库写性能
使用条件
修改的非聚集索引不在缓冲池中
索引是辅助索引
辅助索引是非唯一的
因为唯一索引插入前要判断是否在树中已经重复了,这个查询操作本身就是随机IO无法避免,所以唯一非聚集索引没有使用Insert Buffer的必要
Change Buffer
说明
功能和Insert Buffer基本一致,应用于非唯一性聚集索引的修改优化
,在Insert Buffer的基础上做了细分:Insert、Delete、Purge Buffer
可以通过innodb_change_buffering(inserts、deletes、purges、changes、all、none)来控制启用那些类型的buffer 选项默认为all
,在Insert Buffer的基础上做了细分:Insert、Delete、Purge Buffer
可以通过innodb_change_buffering(inserts、deletes、purges、changes、all、none)来控制启用那些类型的buffer 选项默认为all
Double Write
partitial write的问题定义
innodb的page size是16KB,操作系统的block size一般为4kb,磁盘io可能更小,所以innodb的一次脏页刷新到磁盘不能保证原子性,需要有一个机制来保证这个操作中断时磁盘上不会出现partitial write的问题
innodb 使用double write 来解决partitial write的问题,在对缓冲池的脏页进行flush时,并不直接写磁盘,而是会通过memcpy函数将脏页先复制到内存中的doublewrite buffer,之后通过doublewrite buffer再分两次,每次IMB顺序地写入共享表空间的物理磁盘上,然后马上调用fsync函数,同步磁盘,避免缓冲写带来的问题。在这个过程中,因为doublewrite页是连续的,因此这个过程是顺序写的,开销并不是很大。
可以通过skip_innodb_doublewrite禁用double write 功能
衍生问题:为什么Kafka InfluxDB Redis aof 不需要解决partitial write 的问题?
答案:Mysql 是in-place update 上面的这几个都是append only,不会更新原值
答案:Mysql 是in-place update 上面的这几个都是append only,不会更新原值
自适应哈希索引(AHI)
对于固定模式的等值类查询的优化,辅助索引的查询效率B+树高度的影响,一般高度为3-4的样子,所以一次完成辅助索引搜索需要3-4次查询,AHI就是将多次查询用hashmap的方式优化到一次,但是只对等值类查询生效,DBA不需要关注AHI的,他属于引擎的自优化项
要求
该模式访问了1000次
页通过该模式访问了N(页中记录/16)次
异步IO
同时提交多次IO后等待IO结果,async可以做io request merge ,相比同步IO(提交单个IO等待结果)性能提升明显
innodb 1.1.x之前aio 通过innodb存储引擎代码模拟实现,之后的版本是内核级别的async io实现称为Native AIO
刷新邻接页(Flush Neighbor Page)
刷新脏页的时候检查该页所在的区是否存在脏页,如果存在那么一起刷新
面临的问题
脏页可能不怎么脏,刷新完了立即有变脏了怎么办
固态硬盘相较于机械硬盘IOPS较高,是否需要这个特性
针对上面两个问题,innodb提供配置可开启关闭刷新邻接页,但是机械硬盘强烈建议开启
mysql 文件系统
参数文件
my.conf
日志文件
socket文件
pid文件
表结构定义文件
Innodb存储引擎文件
表空间文件
redo log文件
Innodb 逻辑存储结构
InnoDB逻辑存储结构
段(Segment)
数据段
索引段
回滚段
区(Extend)
1MB大小,包含多个页
页(Page)
Innodb磁盘管理的最小单位,innodb_page_size控制页大小,默认16KB,
补充:在计算机中磁盘存储数据最小单元是扇区,一个扇区的大小是512字节,
而文件系统(例如XFS/EXT4)的最小单元是块(Block),一个块的大小是4k,InnoDB存储引擎一个页的大小是16K。
补充:在计算机中磁盘存储数据最小单元是扇区,一个扇区的大小是512字节,
而文件系统(例如XFS/EXT4)的最小单元是块(Block),一个块的大小是4k,InnoDB存储引擎一个页的大小是16K。
分类
数据页
undo页
系统页
事务数据页
插入缓冲bitmap页
插入缓冲空闲列表页
未压缩二进制大对象页
压缩的二进制大对象页
InnoDB数据是row-oriented
InnoDB的存储格式
几个问题
一个Page里面最少几行数据?
答案:2行,如果少于2行就是列表了,B+树的性能就发挥不出来了。
答案:2行,如果少于2行就是列表了,B+树的性能就发挥不出来了。
一个Page里面行溢出数据怎么办?
溢出的部分会存储到 Uncompress BLOB的页中
溢出的部分会存储到 Uncompress BLOB的页中
页是离散别的放在磁盘上的,不是顺序存储
B+树的节点结构
Infimum 和 Supremum
上下界
User Records
数据记录,叶子节点才有
Free Space
Page Directory
页内部的索引,方便快速查询
B+树的结构
InnoDB锁和事务
锁的类型
独占和排他锁
粒度
该锁的粒度可以是行、页、表
独占锁(X Lock)
共享锁(S Lock)
意向锁
只支持表级锁定,存在意向锁的情况下,事务A必须先申请表的意向共享锁,成功后才能申请表中行的行锁
意向共享锁(IS Lock),表示事务已经获得一张表中某几行的共享锁。
意向排他锁(IX Lock),表示事务已经获得一张表中某几行的排他锁。
IS和IX的I是intention的缩写,意向的意思可以理解为:一个事务在申请行级锁前,先宣称对行所在表的读/写的意向,宣称之后,在不兼容的情况,其他锁就会冲突了。
自增锁(AUTO-INC Locking)
这种锁其实是采用一种特殊的表锁机制,为了提高插人的性能,锁不是在一个事务完成后才释放,而是在完成对自增长值插人的SQL语句后立即释放。
锁的兼容性
两个锁可以同时加锁,称为锁兼容,比如不同的事务可以同时获取同一行的S Lock ;反之不可以同时取锁则为锁不兼容,比如获取了某行的S 锁以后其他事务不能获取该行的X Lock
不同锁之前的兼容性
意向锁内部都兼容,除此之外,意向共享锁只和表级共享锁兼容。
行锁的加锁方式
Record Lock
锁单条记录
Gap Lock
锁定一个范围,不包含记录本身
Next-Key Lock
Record Lock 和Gap Lock的组合,用来锁定一个范围并且包含记录本身
0 条评论
下一页
为你推荐
查看更多