一、Innodb体系架构

1.1、后台线程

后台任务主要负责刷新内存中的数据,保证缓冲池的数据是最近的数据,此外还将修改的数据刷新到文件磁盘,保证在数据库发生异常的情况下Innodb能恢复到正常的运行状态。

1、Master Thread
主要负责缓冲池的数据异步刷新到磁盘,保证数据的一致性,包括脏页的刷新,合并插入缓冲undo页的回收等。

2、IO Thread
主要负责IO请求的回调(call back)(有如下四种io线程)
write IO :innodb_write_io_threads=8
read IO :innodb_read_io_threads=8
insert buffer IO
log IO
查看:show engine innodb status\G (注意:该命令显示不是当前innodb的状态,而是过去一段时间的状态)

--------
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 (read thread)
I/O thread 7 state: waiting for completed aio requests (read thread)
I/O thread 8 state: waiting for completed aio requests (read thread)
I/O thread 9 state: waiting for completed aio requests (read thread)
I/O thread 10 state: waiting for completed aio requests (write thread)
I/O thread 11 state: waiting for completed aio requests (write thread)
I/O thread 12 state: waiting for completed aio requests (write thread)
I/O thread 13 state: waiting for completed aio requests (write thread)
I/O thread 14 state: waiting for completed aio requests (write thread)
I/O thread 15 state: waiting for completed aio requests (write thread)
I/O thread 16 state: waiting for completed aio requests (write thread)
I/O thread 17 state: waiting for completed aio requests (write thread)

从上可以看到IO thread 0为insert buffer thread,IO  thread 1 为log thread,之后的就是根据innodb_write_io_threads=8,innodb_read_io_threads=8设置的读写线程,并且读线程的ID总是小于写线程的ID。

3、Purge Thread
用来回收已经使用并分配的undo页(需要随机读取undo页)
innodb_purge_threads=2  #值相对大点可提高undo页的回收速度,也能更进一步利用磁盘的随机读写性能

查看值的设置:show variables like 'innodb_purge_threads'\G;

4、Page Cleaner Thread
将之前版本脏页的刷新操作都放入单独的线程中完成,减轻master thread的负担和用户查询的阻塞

1.2、内存

Innodb内存结构图

innodb内存数据对象

1、缓冲池

  innodb基于磁盘存储,由于cpu和磁盘之间的速度差距太大,所以通过内存作为一个缓冲,所以缓冲是为了解决磁盘和cpu的速度上差距的问题,提高数据库性能。将磁盘读到的页存放在缓冲中,称为FIX在缓冲池中,从缓冲中读取数据,称为该页在缓冲池被命中。

数据读:先从缓冲池中读取,如果页被命中就返回,否则从磁盘读取
数据写:先修改缓冲池中页的数据,然后以一定的频率(checkpoint机制)刷新到磁盘,不是实时刷新

缓冲池的大小参数:innodb_buffer_pool_size=32G #该值直接影响数据库的整体性能
多个缓冲池实例:innodb_buffer_pool_instances=4 #减少数据内部资源竞争。

sql查看:select POOL_ID,POOL_SIZE,FREE_BUFFERS,DATABASE_PAGES from information_schema.INNODB_BUFFER_POOL_STATS;

查看:show engine innodb status\G

INDIVIDUAL BUFFER POOL INFO
----------------------
---BUFFER POOL 0 #实例1
Buffer pool size 1548287 #页的个数
Buffer pool size, bytes 25367134208
Free buffers 1024 #Free List中页的数量
Database pages 1502522 #LRU List中页的数量
Old database pages 375610
Modified db pages 48677
Percent of dirty pages(LRU & free pages): 3.237
Max dirty pages percent: 50.000
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 422595788, not young 41434529403 #pages made young显示LRU中移动到前端次数,not young表示没能移动到前端次数
0.60 youngs/s, 0.00 non-youngs/s
Pages read 2001192602, created 104217673, written 638270606
0.60 reads/s, 0.00 creates/s, 3.60 writes/s
Buffer pool hit rate 999 / 1000, young-making rate 1 / 1000 not 0 / 1000 #缓冲命中率,越高越好,如果低于95%,则该考虑是否有扫描,数据备份等操作污染了LRU List
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 1502522, unzip_LRU len: 0
I/O sum[1744]:cur[25], unzip sum[0]:cur[0]
---BUFFER POOL 1 #实例2
Buffer pool size 1548287
Buffer pool size, bytes 25367134208
Free buffers 1024
Database pages 1502549
.........

从Innodb的内存对象图看,缓冲数据类型:索引页,数据页,undo页,插入缓冲(insert buffer),自适应哈希索引,数据字典信息等。缓冲池不仅仅只有缓存索引页和数据页,它们只是占缓冲池中很大一部分。

2、LRU List、Free List、Flush List

数据库中的缓冲池是通过LRU(Lastet Recent Used) 最近很少使用算法进行管理。原理:最频繁使用的页放在LRU列前端,不经常使用的放在LUR的后端。

innodb引擎中,缓冲池中的页默认大小16k,虽然使用了LRU管理,但是在其中间加入了midpoint点(可以理解为把LRU列分为两段),一段为频繁使用,一段为很少使用,通过参数:innodb_old_blocks_pct=30,(意思为30%)控制比例。

加midpoint的优点:像扫描类的操作很容易将其他常用的页刷新出去,导致效率下降,midpoint可以解决这个问题。另外innodb_old_blocks_time控制列进去LRU进去热端的时间,这样可以保证热端的页的访问频率比较高。

LRU列是用来管理已读取到的页,当服务刚启动的时候,LRU为空,页都在Free列中,从Free中读取空闲页到LRU中,并删除Free中的页LRU中页从old到new端称为page made young,因innodb_old_blocks_time而没能从old到new端称为page not made young。查看:show engine innodb status\G(如上代码框中)

Flush列管理脏页(modified db pages),管理将页刷回磁盘,与LRU不影响,LRU用于管理缓冲池中可用的列

3、重做日志缓冲

innodb先将重做日志信息存放在这个缓冲中,然后按照一定的频率将其刷新到重做日志文件中
参数控制:innodb_log_buffer_size=8M (一般不需要很大,因为每秒会刷缓存到日志文件中)

重做日志缓冲刷新条件:
1.master Thread每一秒将缓冲刷入重做日志文件中
2.每个事务提交会将重做日志缓冲刷入重做日志文件
3.当重做日志缓冲剩下不到1/2时,会刷入重做日志文件

4、额外内存池

在innodb的引擎中,对内存的管理是通过一种为内存堆的方式进行管理,对一些数据的内存分配时,需要从额外的内存池中申请,如果额外内存池资源不够,就会从缓冲池中申请。

二、checkpoint

为了防止数据丢失:采用Write Ahead Log策略,提交事务时,先写重做日志,然后再修改页,就算在从缓冲池中刷新到磁盘过程中宕机,也可以从日志中恢复数据,防止数据丢失。

checkpoint技术特点:
1.缩短数据库的恢复时间(把日志生成数据到磁盘,直接加载磁盘数据,而不是通过日志重新恢复数据)
2.缓冲池不够用,将脏页写入磁盘
3.重做日志不可用,刷新脏页

checkpoint种类:
sharp checkpoint:发生在数据库关闭时将所有数据刷回磁盘(默认工作方式,innodb_fast_shutdown=1)
fuzzy checkpoint:只刷新部分脏页,而不是所有脏页到磁盘

fuzzy checkpoint发生条件:
master Thread checkpoint :主线程定时checkpoint
FLUSH_LRU_LIST checkpoint :LRU列不够存
Async/Sync Flush checkpoint :重做日志不可用,保证重做日志的循环利用
Dirty page too much checkpoint :脏页数量过多 innodb_max_dirty_pages_pct

三、Innodb关键特性

3.1 插入缓冲

insert buffer

聚集索引:也叫聚簇索引。数据行的物理顺序与列值(一般是主键的那一列)的逻辑顺序相同,一个表中只能拥有一个聚集索引。

非聚集索引(辅助索引):该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以拥有多个非聚集索引。

innodb对于非聚集索引的插入和更新操作,不是每一次插入到索引页中,而是先判断非聚集索引页是否在缓冲池中,如在,则直接插入,若不在,则先放入一个insert buffer中,然后再以一定的频率和情况进行insert buffer 和辅助索引页子节点的合并,这是通常能将多个插入操作合并成一个操作。这就大大提高了非聚集索引的效率

insert buffer发生必须满足两个条件:
1、所以必须是辅助索引
2、索引不是唯一的

存在的问题:当遇到大量的写入时,插入缓冲会占用太多的缓冲池内存,最大默认为1/2,

change buffer(插入缓冲升级版)

这个版本的的插入缓冲可以对DML操作--insert、delete、update进行缓冲,分别是insert buffer, delete buffer , purge buffer

innodb_change_buffer_max_size #该参数用来控制changer buffer的最大值,默认为25,也就是1/4,最大可为50

查看:show engine innodb status\G

-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 948959, seg size 948961, 870033008 merges
merged operations:
insert 4536471183, delete mark 24386361779, delete 4019249458
discarded operations:
insert 11214, delete mark 0, delete 0
449.91 hash searches/s, 426.91 non-hash searches/s

如上包括了merged operation和discarded operation。其中的数字表示次数,insert表示insert buffer,delete mark 表示delete buffer,delete 表示purge buffer。discarded opreation的操作表示merge时删除了,无需再合并到索引中。

change insert底层实现:B+tree (不详述)

merge insert buffer发生情况:

1.辅助索引页被读取到缓冲池时
2.master thread
3.辅助索引页无可用空间

3.2 两次写

InnoDB的Page Size一般是16KB,其数据校验也是针对这16KB来计算的,将数据写入到磁盘是以Page为单位进行操作的。我们知道,由于文件系统对一次大数据页(例如InnoDB的16KB)大多数情况下不是原子操作,这意味着如果服务器宕机了,可能只做了部分写入。16K的数据,写入4K时,发生了系统断电/os crash ,只有一部分写是成功的,这种情况下就是partial page write问题。

double write基本思路:就是在写数据页之前,先把这个数据页写到一块独立的物理文件位置(ibdata),然后再写到数据页。这样在宕机重启时,如果出现数据页损坏,那么在应用redo log之前,需要通过该页的副本来还原该页,然后再进行redo log重做。

 double write组成:一部分是InnoDB内存中的double write buffer,大小为2M,另一部分是物理磁盘上ibdata系统表空间中大小为2MB,共128个连续的Page,既2个分区。其中120个用于批量写脏,另外8个用于Single Page Flush。做区分的原因是批量刷脏是后台线程做的,不影响前台线程。而Single page flush是用户线程发起的,需要尽快的刷脏并替换出一个空闲页出来。

double write工作流程:当一系列机制(main函数触发、checkpoint等)触发数据缓冲池中的脏页进行刷新到data file的时候,并不直接写磁盘,而是会通过memcpy函数将脏页先复制到内存中的double write buffer,之后通过double write buffer再分两次、每次1MB顺序写入共享表空间的物理磁盘上(ibdata)。然后马上调用fsync函数,同步脏页进磁盘上。由于在这个过程中,double write页的存储时连续的,因此写入磁盘为顺序写,性能很高;完成double write后,再将脏页写入实际的各个表空间文件,这时写入就是离散的了。如图所示:

查看:show GLOBAL STATUS like '%innodb_dblwr%'

Innodb_dblwr_pages_written :5166155016   #表示double write一共写了页的数量,可以用来数据的写入量

Innodb_dblwr_writes :87244238  #实际写入的次数

skip_innodb_doublewrite:用来禁用double write

3.3 自适应哈希索引

定义:Innodb存储引擎会监控对表上各个索引页的查询,如果觉得建立哈希索引能够带来性能的提升,则建立哈希索引,称为自适应哈希索引(AHI)。

AHI是通过B+树构造而来,因此建立的速度很快,而且不需要对整个表构建哈希索引,Innodb会自动根据访问的频率和模式来自动地为某些热点建立哈希索引。

AHI要求:对一个页的访问模式必须是一样的,访问模式一样,指的是查询条件一样。

注意:AHI只用来搜索等值查询,例如where a=1

查看:show engine innodb status\G

INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 948959, seg size 948961, 870033008 merges
merged operations:
insert 4536471183, delete mark 24386361779, delete 4019249458
discarded operations:
insert 11214, delete mark 0, delete 0
449.91 hash searches/s, 426.91 non-hash searches/s
---
LOG

3.4 异步IO

异步IO(AIO):允许用户在发出一个IO请求后立即发送第二个IO请求,当全部的IO请求发送完毕后,等待所有的IO操作的完成。

优势:可以合并多个IO,提高IPIOPS性能

控制参数:innodb_use_native_aio

3.5 刷新邻接页

工作原理:当刷新一个脏页时,Innodb会检测到该页所在区的所有页,如果是脏页,则一起刷新

四、Innodb启动与关闭

4.1启动

innobase_start_or_create_for_mysql函数用来控制innodb的启动,基本启动流程如下:

1、初始化:

同步控制系统,内存管理系统,日志恢复变量,后台线程同步控制系统

根据innodb_buffer_pool_size和innodb_buffer_pool_instances初始化Buffer pool

初始化日志系统,包括日志的写入,LSN的管理,检查点,日志刷盘以及日志恢复等

IO异步线程,创建innodb_read_io_threads+innodb_write_io_threads个IO线程

初始化日志恢复系统

2、打开或者创建系统数据文件(ibdata)

open_or_create_data_files函数控制,如果存在,则读取信息并打开,如果不存在,则创建,相当于初始化一个新的数据库实例。

。。。。。。

4.2关闭

参考:《msyql技术内幕,Innodb存储引擎》

mysql之innodb存储引擎介绍的更多相关文章

  1. 关于MySql 数据库InnoDB存储引擎介绍

    熟悉MySQL的人,都知道InnoDB存储引擎,如大家所知,Redo Log是innodb的核心事务日志之一,innodb写入Redo Log后就会提交事务,而非写入到Datafile.之后innod ...

  2. MySQL数据库InnoDB存储引擎中的锁机制

    MySQL数据库InnoDB存储引擎中的锁机制    http://www.uml.org.cn/sjjm/201205302.asp   00 – 基本概念 当并发事务同时访问一个资源的时候,有可能 ...

  3. MySQL数据库InnoDB存储引擎多版本控制(MVCC)实现原理分析

    文/何登成 导读:   来自网易研究院的MySQL内核技术研究人何登成,把MySQL数据库InnoDB存储引擎的多版本控制(简称:MVCC)实现原理,做了深入的研究与详细的文字图表分析,方便大家理解I ...

  4. MySql中innodb存储引擎事务日志详解

    分析下MySql中innodb存储引擎是如何通过日志来实现事务的? Mysql会最大程度的使用缓存机制来提高数据库的访问效率,但是万一数据库发生断电,因为缓存的数据没有写入磁盘,导致缓存在内存中的数据 ...

  5. InnoDB存储引擎介绍-(2)redo和undo学习

    01 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版本并发控制(简称:MVCC). - 事务的原子性(Atomi ...

  6. MySQL数据库InnoDB存储引擎

    MySQL数据库InnoDB存储引擎Log漫游  http://blog.163.com/zihuan_xuan/blog/static/1287942432012366293667/

  7. mysql中InnoDB存储引擎的行锁和表锁

    Mysql的InnoDB存储引擎支持事务,默认是行锁.因为这个特性,所以数据库支持高并发,但是如果InnoDB更新数据的时候不是行锁,而是表锁的话,那么其并发性会大打折扣,而且也可能导致你的程序出错. ...

  8. mysql之innodb存储引擎

    mysql之innodb存储引擎 innodb和myisam区别 1>.InnoDB支持事物,而MyISAM不支持事物 2>.InnoDB支持行级锁,而MyISAM支持表级锁 3>. ...

  9. mysql innodb存储引擎介绍

    innodb存储引擎1.存储:数据目录.有配置参数为“ innodb_data_home_dir ” .“ innodb_data_file_path ” 和 “innodb_log_group_ho ...

随机推荐

  1. C# 一个计算器功能实现引发的思考

    一.需求 计算器功能需求,这个众所周知,很明确了. 二.步骤分析 1)初级实现计算器 static int Calculator(int a,int b,string str) { switch(st ...

  2. linux command line learn - get the absolute path of a file

    get the absolute path of a file in linux readlink -f filenme [heshuai@login01 3_Variation_calling]$ ...

  3. sparksession创建DataFrame方式

    spark创建dataFrame方式有很多种,官方API也比较多 公司业务上的个别场景使用了下面两种方式 1.通过List创建dataFrame /** * Applies a schema to a ...

  4. Oracle数据库之SQLPLUS

    三.SQLPLUS ​ SQLPlus 是 Oracle 数据库提供的一个专门用于数据库管理的交互式工具,使用 SQLPlus 可以管理 Oracle 数据库的所有任务,SQLPlus 通过命令的方式 ...

  5. C#中的变量祥解

    一.C#数据类型: A:值类型 值类型变量可以直接分配一个值,它是从System.ValueType派生而来,值类型直接包含数据,比如int,char,float,他们分别存储整型数据,字符,浮点数, ...

  6. 持续集成高级篇之Jekins脚本参数化构建

    系列目录 本系列已经很久没有更新了,接前面基础篇,本系统主要介绍jenkins构建里的一些高级特性.包括脚本参数化,Jenkins Pipeline与及在PipeLine模式下如何执行常见的传统构建任 ...

  7. Kibana 管理界面使用教程

    使用浏览器访问 ip:5601 默认端口,进入首页 Discover:日志管理视图 Visualize:统计视图 Dashboard:仪表视图 Timelion:时间轴视图 APM:性能管理视图 De ...

  8. Codeforces 1008D/1007B

    题意略. 思路: 由于这个长方体是可以翻转的,所以我们不必考虑小长方体3个维度的出处,反正3条边一定有长有短能分出大小. 现在我们来考虑A,B,C三个数字,如果它们3个产生的因子互不相同,分别产生了a ...

  9. 12 redis搭建主从服务(ubuntu)

    什么是主从服务 一个master可以拥有多个slave,一个slave可以拥有多个slave,如此下去,形成了多级服务器集群架构 master用来写数据, slave用来读数据, 经统计:网站的读写比 ...

  10. Mysql系列 - 第3天:管理员必备技能(必须掌握)

    这是mysql系列第3篇文章. 环境:mysql5.7.25,cmd命令中进行演示. 在玩mysql的过程中,经常遇到有很多朋友在云上面玩mysql的时候,说我创建了一个用户为什么不能登录?为什么没有 ...