MySQL(进阶篇--InnoDB引擎)

文章目录

  • InnoDB
  • 一、逻辑存储结构
  • 二、架构
    • 总结构
    • 2.1 内存结构
    • 2.2 磁盘结构
    • 2.3 后台线程
    • 总结
  • 三、事务原理
    • 3.1 redo log
    • 3.2 undo log
  • 四、MVCC
  • 五、总结

InnoDB

一、逻辑存储结构

MySQL(进阶篇--InnoDB引擎)_第1张图片
MySQL(进阶篇--InnoDB引擎)_第2张图片

二、架构

总结构

MySQL5.5 版本开始,默认使用InnoDB存储引擎,它擅长事务处理,具有崩溃恢复特性,在日常开发中使用非常广泛。
下面是InnoDB架构图,侧为内存结构侧为磁盘结构

MySQL(进阶篇--InnoDB引擎)_第3张图片

2.1 内存结构

MySQL(进阶篇--InnoDB引擎)_第4张图片
在左侧的内存结构中,主要分为这么四大块儿: Buffer Pool、Change Buffer、Adaptive
Hash Index、Log Buffer。

1). Buffer Pool
InnoDB存储引擎基于磁盘文件存储,访问物理硬盘和在内存中进行访问,速度相差很大,为了尽可能
弥补这两者之间的I/O效率的差值,就需要把经常使用的数据加载到缓冲池中,避免每次访问都进行磁
盘I/O。 在InnoDB的缓冲池中不仅缓存了索引页和数据页,还包含了undo页、插入缓存、自适应哈希索引以及
InnoDB的锁信息等等。

缓冲池 Buffer Pool,是主内存中的一个区域,里面可以缓存磁盘上经常操作的真实数据,在执行增
删改查操作时,先操作缓冲池中的数据(若缓冲池没有数据,则从磁盘加载并缓存),然后再以一定频
率刷新到磁盘,从而减少磁盘IO,加快处理速度。

缓冲池以Page页为单位,底层采用链表数据结构管理Page。
根据状态,将Page分为三种类型:
• free page:空闲page,未被使用。
• clean page:被使用page,数据没有被修改过。
• dirty page:脏页,被使用page,数据被修改过,也中数据与磁盘的数据产生了不一致。
在专用服务器上,通常将多达80%的物理内存分配给缓冲池 。参数设置: show variables
like ‘innodb_buffer_pool_size’;
MySQL(进阶篇--InnoDB引擎)_第5张图片

2). Change Buffer

Change Buffer,更改缓冲区(针对于非唯一二级索引页),在执行DML语句时,如果这些数据Page
没有在Buffer Pool中,不会直接操作磁盘,而会将数据变更存在更改缓冲区 Change Buffer
中,在未来数据被读取时,再将数据合并恢复到Buffer Pool中,再将合并后的数据刷新到磁盘中。

Change Buffer的意义是什么呢?

MySQL(进阶篇--InnoDB引擎)_第6张图片
与聚集索引不同,二级索引通常是非唯一的,并且以相对随机的顺序插入二级索引。同样,删除和更新
可能会影响索引树中不相邻的二级索引页,如果每一次都操作磁盘,会造成大量的磁盘IO。有了
ChangeBuffer之后,我们可以在缓冲池中进行合并处理,减少磁盘IO。

MySQL(进阶篇--InnoDB引擎)_第7张图片

3). Adaptive Hash Index

自适应hash索引,用于优化对Buffer Pool数据的查询。MySQL的innoDB引擎中虽然没有直接支持
hash索引,但是给我们提供了一个功能就是这个自适应hash索引。因为前面我们讲到过,hash索引在
进行等值匹配时,一般性能是要高于B+树的,因为hash索引一般只需要一次IO即可,而B+树,可能需
要几次匹配,所以hash索引的效率要高,但是hash索引又不适合做范围查询、模糊匹配等。

InnoDB存储引擎会监控对表上各索引页的查询,如果观察到在特定的条件下hash索引可以提升速度,
则建立hash索引,称之为自适应hash索引。

自适应哈希索引,无需人工干预,是系统根据情况自动完成。
参数: adaptive_hash_index

4). Log Buffer

Log Buffer:日志缓冲区,用来保存要写入到磁盘中的log日志数据(redo log 、undo log),
默认大小为 16MB,日志缓冲区的日志会定期刷新到磁盘中。如果需要更新、插入或删除许多行的事
务,增加日志缓冲区的大小可以节省磁盘 I/O。

参数:
innodb_log_buffer_size:缓冲区大小
innodb_flush_log_at_trx_commit:日志刷新到磁盘时机,取值主要包含以下三个:
1: 日志在每次事务提交时写入并刷新到磁盘,默认值。
0: 每秒将日志写入并刷新到磁盘一次。
2: 日志在每次事务提交后写入,并每秒刷新到磁盘一次。

MySQL(进阶篇--InnoDB引擎)_第8张图片

2.2 磁盘结构

MySQL(进阶篇--InnoDB引擎)_第9张图片
①:System Tablespace:系统表空间是更改缓冲区的存储区域。如果表是在系统表空间而不是每个表文件或通用表空间中创建的,它也可能包含表和索引数据。(MySQL5.x版 本中还包含InnoDB数据字典、undolog等)
参数: innodb_ data_ file_ path

②:File-Per-Table Tablespaces:每个表的文件表空间包含单个InnoDB表的数据索引,并存储在文件系统.上的单个数据文件中。
参数: innodb_ file_ per_ table

默认是开启的;开启就意味着每张独立的表都有一个表空间,并不会再①中存放;

ibd文件每一个文件都是一个表空间文件,其中存放的就是这张表的表结构及表中的数据和索引;

③:General Tablespaces:通用表空间,需要自己通过CREATE TABLESPACE语法创建用表空间,在创建表时,可以指定该表空间。(了解)

创建:
MySQL(进阶篇--InnoDB引擎)_第10张图片

create tablespace a_stu(随意别名) add datafile 'student.ibd' engine = innodb;

使用:

create table a(id int primary key auto increment,name varchar (10)) engine = innodb tablespacets a_stu;

④:Undo Tablespaces:撤销表空间,MySQL 实例在初始化时会自动创建两个默的undo表空间(初始大小16M),用于存储undo log日志。

⑤:Temporary Tablespaces:临时表空间。 InnoDB 使用会话临时表空间和全局临时表空间。存储用户创建的临时表等数据。

⑥:Doublewrite Buffer Files:双写缓冲区,innoDB引擎将数据页从Buffer Pool新到磁盘前,先将数据页写入双写缓冲区文件中,便于系统异常时恢复数据。

在这里插入图片描述
⑦:RedoLog:重做日志,是用来实现事务的持久性。该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log) ,前者是在内存中,后者在磁盘中。当事务提交之后会把所有修改信息都会存到该日志中,用于在刷新脏页到磁盘时,发生错误时,进行数据恢复使用。

以循环方式写入重做日志文件,涉及两个文件:在这里插入图片描述

**redo log:**它是循环写的,不会永久保存,每隔一段时间,清理之前没有用的redo log;因为redo log,当事务提前,也就没什么用了,因为它的作用是保证异常时,
继续数据恢复,从而保证事务的持久性;

2.3 后台线程

MySQL(进阶篇--InnoDB引擎)_第11张图片
数据如何从内存写入磁盘的,就是这中间部分:后台线程

MySQL(进阶篇--InnoDB引擎)_第12张图片
MySQL(进阶篇--InnoDB引擎)_第13张图片

总结

整个体系结构就是:当我门业务操作的时候,那么会直接操作左边内存的缓冲区,如果缓冲区当中没有数据,会将右边磁盘当中的数据加载回来,然后再存储在缓存区当中;我门在增删改查的时候,都会去操作左边的缓冲区,然后缓冲区当中的数据会以一定的频率或者说一定的时机,要通过这组后台线程刷新到磁盘当中,然后再磁盘当中进行永久化保存(永久保存主要指的是我门表当中的数据和索引等相关信息,undo log和read log会被回收释放,不会永久保留);

三、事务原理

MySQL(进阶篇--InnoDB引擎)_第14张图片
底层:
MySQL(进阶篇--InnoDB引擎)_第15张图片

3.1 redo log

MySQL(进阶篇--InnoDB引擎)_第16张图片
无redo log情况:
MySQL(进阶篇--InnoDB引擎)_第17张图片

首先,客户端在进行事务操作时会发起请求去操作MySql服务器,在MySQL的InnoDB引擎中,分为内存结构和磁盘结构,磁盘结构里存放了很多ibd文件,内存结构中有一个很大的缓冲池,缓冲池中缓冲了我们很多数据页的信息。当客户端发起事务操作,在这次事务操作中,包含了多条update和delete语句,那么此时是怎么进行执行的呢?
首先,去操作缓冲区,在缓冲区中查找有没有对应操作的数据,如果没有,此次会通过后台线程把我们数据从磁盘中读取出来,然后缓存在缓冲区中;接下来就可以直接在缓冲区中执行客户发送的事务操作;此时,缓冲区中的数据就会发生变更,而磁盘中的数据没有变更,那么缓冲区中这个变更的数据页就叫脏页,会在一定时机,通过后台线程将其刷新至磁盘中,这个时候内存中的缓冲区和磁盘中数据就一致了。
但是脏页的数据并不是实时刷新的,而是一段时间或者一段频率刷新的,假如,脏页的数据往磁盘中刷新出错了,那么内存中的数据就没刷新到磁盘中。那么,事务都已经提交了并通知了用户成功,但最终在脏页刷新的时候失败了,那么持久性就没得到保障!

有redo log情况:
MySQL(进阶篇--InnoDB引擎)_第18张图片

脏页数据从内存刷新到磁盘出现错误时,恢复用的,保证持久性。
为什么每次提交时要把redo log刷新到磁盘中?
提交事务时,不先将脏页直接刷新,先把redo log文件异步刷新到磁盘当中,由于是
log日志文件,日志文件都是追加的,此时就是顺序磁盘IO,效率远高于随机磁盘IO。
这种机制就是WAL(先写日志),日志是循环写,不会永久保留,这就是redo log。

3.2 undo log

MySQL(进阶篇--InnoDB引擎)_第19张图片

四、MVCC

MySQL(进阶篇--InnoDB引擎)_第20张图片

五、总结

MySQL(进阶篇--InnoDB引擎)_第21张图片

你可能感兴趣的:(数据库,mysql,java,jvm)