InnoDB存储引擎是MySql第一个完整支持事务的存储引擎,最早由第三方公司开发,并不是MySql的官方引擎,在MySql 5.6后被作为默认引擎推出。
特点
InnoDB设计是为OLTP(在线事务处理类型)应用设计,支持事务是最大的特点,此外还有如下特点:
- 事务:完整的ACID及4级事务隔离级别支持;
- 基于行锁设计:支持行锁、表锁,可通过扩展sql主动S和X锁,不能主动加表锁;
- 支持外键:可以设定外键及外键的完整性约束;
- 支持MVVC:多版本并发控制技术,实现了多个版本数据的读写;
- 一致性非锁定读:类似Oracle,提高并发,不是所有的读都会加锁,大部分读不加锁;
InnoDB的版本
InnoDB的跨界版本是1.0.x,建议使用最新版本获取更好的性能;
体系结构
InnoDB能很好的利用内存和CPU,它的大部分操作都是利用异步IO技术,屏蔽磁盘和内存的速度差,从而获得更高的性能;
- 多个后台线程:通过多个后台线程,每个线程完成自己的任务,后台线程的主要作用是刷新内存池中的数据,保持磁盘和内存数据一致;
- 内存池:使用内存缓冲技术,建立多种缓冲池来缓冲数据、索引,内存管理采用基于页的管理方式,让读写效率更高;
InnoDB的核心线程
- Master Thread:核心线程,将数据异步刷新到磁盘,分为多种状态,每秒、每10秒的处理逻辑都不同;
- IO Thread : 采用AIO异步刷新数据到磁盘;
- Purge Thread:清理线程,实际执行update、insert、delete操作,回收undo页;
- Page Cleander Thread:刷新脏页数据到磁盘,保持数据同步;
内存池
InnoDB通过内存池技术来解决磁盘读写速度问题,其内存池管理结构如下:
可以看到,InnoDB是通过页的方式来管理数据,类似操作系统的内存管理方式,热点页常驻内存,采用LRU等算法进行页的管理,InnoDB通过多种参数和配置可以影响内存池大小和数据页的换入换出。
InnoDB每个page的大小是16k
内存池参数
在mysql中可以通过如下参数影响InnoDB内存池的大小及行为:
观察InnoDB状态:Show engine innodb status \G
内存池大小:innodb_buffer_pool_size;
page被hit多少次后加入LRU列表的热点区:innodb_old_blocks_time
InnoDB状态参数的含义:
Buffer Pool Hit Rate : 缓存命中策略 不应该小于 95%
Free Buffers + Buffer Pool Size != DataBase Size
重做日志
为了实现数据库事务,基本上所有的数据库引擎都需要重做日志,重做日志包括:redo log 和undo log,统称重做日志,重做日志保证了事务的原子性、一致性、持久性,但是重做日志本身会带来开销。
Checkpoint技术
检查点技术被很多需要保证系统高可用的程序采用,InnoDB为了解决磁盘的速度问题,采用内存缓冲方式,也就是很多最新的数据都是在内存中的,但是内存不是持久的,一旦内存断电,这些修改和操作没有更新到物理文件中,那么就会造成数据的丢失和不一致性。InnoDB使用一些技术来保证不会发生这些情况。
InnoDB采用两种方式将数据异步刷新到磁盘,保证高可用和数据一致性:
- 通过多线程,尤其是核心Master Thread使用一些策略来将数据、日志、操作刷新到磁盘;
- 检测点技术,在一些关键的点上触发磁盘操作,将数据、日志、操作刷新到磁盘;
InnoDB的检查点技术主要目的:
- 缩短数据库恢复时间:减少恢复数据量;
- 缓冲池不够的时候,将脏页刷新到磁盘,释放缓冲或者防止数据不一致;
- 重做日志不可用时,刷新到磁盘,防止重做日志丢失;
Checkpoint的核心技术是通过LSN(log sequence number)来标记版本号,很多增量备份工具也是使用这个特性。
Checkpoint的触发时机:
- 数据库关闭时,触发Sharp Checkpoint;
- Master Thread 每十几秒触发一次 Fuzzy Checkpoint;
- 页空间不足的时候时触发Fuzzy Checkpoint;
- 重做日志不足,这时磁盘空间不够了,日志达到了指定大小,覆盖日志失败了,都触发Fuzzy Checkpoint;
- 内存池中脏页太多触发Fuzzy Checkpoint。
InnoDB的一些关键技术
关键技术和特性不一样,关键技术是实现过程中的一些做法,这些做法带来了特性。下面是InnoDB采用的一些关键技术,有些是独创的,极大的提高了InnoDB的性能。
- 插入缓冲:insert buffer,解决辅助索引的插入性能问题;
- 两次写:double write,提高数据的可靠性,保证数据一致;
- 自适应哈希索引:adaptive hash index,提升索引效率;
- 异步IO:Async IO,使用异步IO不进行同步等待,可以一次发出多个IO指令,底层还会合并多个IO到一次IO;
- 刷新邻接表:提升脏页刷新效率。
Insert Buffer
对于非聚集类索引,也叫辅助索引,如果索引不是唯一的,不需要做唯一性校验,InnoDB会先将索引放入到缓冲区不会每次都调整索引的B+树,大致思路:
- 每次insert的时候,如果辅助索引字段不是唯一的,不需要做唯一性校验;
- InnoDB 先不去实际insert index,不刷新磁盘,也不会产生B+树的旋转,也就不会引起随机的IO,等到一定时机,将多个索引的insert merge为一个insert,提高索引的插入效率。
merge insert buffer的时机:
- 辅助索引页被读取到缓冲池中;
- Insert Buffer Bitmap追踪到辅助索引页无可用空间;
- Master Thread触发;
Double Write
提高数据可靠性,尤其是将脏页刷新到磁盘的时候,防止如果部分写入失败了,那么将产生数据不一致情况;
自适应Hash索引
InnoDB通过监控B+ Tree的索引,如果适用Hash索引,则建立Hash索引。在实际生产环节中,B+ Tree的高度一般为3 - 4,需要 3 - 4的逻辑IO,远没有Hash索引快。
Hash索引仅适用于等值索引,不适合范围索引,也就是如果频繁的用where id > ‘100’ 这类操作不会建立自适应Hash索引。
AIO
异步IO,连续发出多个IO,进行IO Merge,提升磁盘的IOPS。
刷新邻接表
刷新dirty的page时会检查这个page所在的区域的所有page,如果这些page也是dirty,则一起刷新,通过AIO的merge操作,提升性能。机械硬盘有很大用途;