本系列是mysql技术内幕-innodb存储引擎一书的笔记总结
一、Innodb存储引擎
1.1 体系架构
1.1.数据库文件
.frm: myisam和innodb存储引擎的表结构文件
.MYI: myisam存储引擎的表索引文件
.MYD: myisam存储引擎的表数据文件
.ibd: innodb存储引擎的索引文件和数据文件
mysql是单进程多线程架构,插件式存储引擎,存储引擎是基于表的
每张表的存储是按主键顺序进行存放,若没显式指定主键,会字动生成6字节rowid作为主键
myisam只缓存索引文件,数据文件的缓存由操作系统负责
mysql> show engines\G
1.2主要线程介绍
1.2.1 后台线程
作用:刷新内存池中数据,将修改的数据刷写到磁盘,保证mysql异常情况下能恢复到正常运行状态
master thread:核心后台线程,将缓冲池中数据异步刷新到磁盘,保证数据一致性
io thread:使用了aio来处理写io请求,负责io请求回调处理
> show variables like 'innodb_%io_threads'; +-------------------------+-------+ | Variable_name | Value | +-------------------------+-------+ | innodb_read_io_threads | 4 | | innodb_write_io_threads | 4 | +-------------------------+-------+ > show engine innodb status\G 查看io thread情况 I/O thread 0 state: waiting for completed aio requests (insert buffer thread) I/O thread 1 state: waiting for completed aio requests (log thread) I/O thread 2 state: waiting for completed aio requests (read thread) I/O thread 3 state: waiting for completed aio requests (read thread) I/O thread 4 state: waiting for completed aio requests (read thread) I/O thread 5 state: waiting for completed aio requests (read thread) I/O thread 6 state: waiting for completed aio requests (write thread) I/O thread 7 state: waiting for completed aio requests (write thread) I/O thread 8 state: waiting for completed aio requests (write thread) I/O thread 9 state: waiting for completed aio requests (write thread)
purge thread:作用是用来回收已经使用并分配的undo页,老版本该线程在master thread中,新版本可以使用独立的,需要在配置文件中设置
innodb_purge_threads=1 > show variables like 'innodb_purge_threads'; +----------------------+-------+ | Variable_name | Value | +----------------------+-------+ | innodb_purge_threads | 4 | +----------------------+-------+
page cleaner thread: 从master thread中独立出来,负责脏页刷新
1.3 内存
1.3.1 缓冲池
对页的修改,先修改缓冲池中的页,再以一定频率刷写到磁盘
刷写磁盘通过checkpoint机制完成
缓冲池中缓存的类型有:索引页,数据页,undo页,insert buffer,自适应哈希索引,锁信息,数据字典信息等
允许多个缓冲池,默认是1个
> show variables like 'innodb_buffer_pool_instances'; > show engine innodb status\G 查看目前缓冲池情况 也可以通过information_schema中的innodb_buffer_pool_stats表查看缓存状态
缓冲池管理使用改进的LRU算法
脏页:缓冲池中数据与磁盘数据不一样
1.3.2 redo log buffer
- 一般不需要设置太大,一般每秒钟刷新一次redo log buffer到redo log中,该值大小由innodb_log_buffer_size,默认8mb
- 以下三种情况,会将buffer中内容刷写到磁盘redo log中
- master thread每秒钟会刷写一次
- 每个事务提交时会刷写
- 当redo log buffer 剩余空间小于1/2,会刷写
1.3.2 额外内存池
- innodb对内存管理使用内存堆方式
1.4 checkpoint技术
- 为避免在缓冲中刷写磁盘时发生宕机,数据库普遍采用write ahead log策略,即当事务提交时,先写重做日志,再修改页。一旦宕机,通过redo log来完成数据恢复,这是acid中持久性的要求
- check point解决以下问题:
- 缩短数据库恢复时间
- 缓冲池不够时,将脏页刷写到磁盘
- 重做日志不可用,刷新脏页
- 数据库宕机,只需对checkpoint后的重做日志进行恢复,
- 当进行LRU时,溢出的页若为脏页,那就要强制执行checkpoint,将脏页刷写到磁盘
- 重做日志是循环使用的,不需要的数据可以被覆盖
- innodb通过lsn来标记版本,重做日志,每个页,checkpoint都有lsn,可以通过show engine innodb status来查看
- 有两种checkpoint:
- sharp checkpoint:在数据库关闭时将所有脏页都刷写到磁盘,这是默认的,即innodb_fast_shutdown=1
- fuzzy checkpoint:但在数据库运行时也使用sharp checkpoint,数据库可用性会收很大影响,此时使用fuzzy checkpoint进行页刷新,只刷新部分脏页,而不是所有脏页
- 以下情况会发生fuzzy checkpoint:
- master thread checkpoint
- flush_lru_list checkpoint
- Async/sync flush checkpoint
- dirty page too much chekpoint: innodb_max_dirty_pages_pct参数控制,当脏页数大于该参数值,强制checkpoint,刷新一部分脏页到磁盘
- 以下情况会发生fuzzy checkpoint:
1.5 innodb关键特性
insert buffer:在innodb中,主键是行唯一的标识符,行插入顺序是按主键递增的顺序插入,并不是所有主键插入都是顺序的,插入聚集索引一般是按顺序的,不需要磁盘的随机读取,一张表也会有辅助索引,这些索引插入不一定是顺序的
- 对于非聚集索引的插入或更新,不是每一次直接插入到索引页中,而是先判断插入的非聚集索引是否在缓冲池中,在就直接插入,不在,则先放入一个insert buffer对象中
- insert buffer使用需要同时满足两个条件:索引是辅助索引,索引不是唯一的
change buffer:引入inset buffer,delete buffer, purge buffer
两次写:doublewrite
- 数据库宕机,会通过重做日志进行恢复,但redo log中记录的是对页的物理操作,如偏移量800,写‘aaa’记录,如果这个页本身发生损坏,再进行重做是没意义的
- 双写就是在apply重做日志之前,需要一个页的副本,当写入失效,先通过页的副本来还原该页,再进行重做
- innodb_doublewrite 可以设置是否使用doublewrite,在从服务器需要较快性能,可以关闭,需要数据高可靠性的数据库上应该开启此参数,如果文件系统提供了写失效的防范机制,也可以关闭
异步io
1.6 重要参数
innodb_fast_shutdown
0:数据库关闭时,innodb需要完成所有的full purge和merge insert buffer操作,并将所有脏页刷写到磁盘。这需要一定时间,若进行innodb升级,必须设置为0,然后在关闭数据库
1:默认值,不需要完成full purge和merge insert buffer操作,但脏数据要刷写到磁盘
2: 不完成full purge和merge insert buffer操作,也不将脏页写入磁盘,而是写入日志文件。这样没有任何事务丢失,下次启动数据库,会进行恢复操作
某些情况,不需要进行完整恢复,如用户直到如何恢复,进行完整恢复时间会很长,这时可以用户自己进行恢复
innodb_force_recovery:
0:默认为0,当发生需要恢复操作时,进行所有恢复操作,当不能有效恢复,如mysql crash,把错误写入到错误日志
1:忽略检查到的corrupt页
2:阻止master thread线程的运行,如master thread需要进行full purge,而这会导致mysql crash
3:不进行事务回滚操作
4:不进行insert buffer的合并操作
5:不查看undolog,innodb会将未提交的事务视为已提交
6:不进行前滚操作
设置大于0的值,可以对表进行select,create,drop。但insert,update,delete操作