012、MySQL InnoDB引擎
本文最后更新于 65 天前,其中的信息可能已经过时,如有错误请发送邮件到wuxianglongblog@163.com

MySQL InnoDB引擎

一、InnoDB逻辑存储结构

  • 表空间(ibd文件):一个MySQL实例可以对应多个表空间,用于存储记录,索引等数据。
  • :分为数据段、索引段、回滚段,InnoDB是索引组织表,数据段就是B+树的叶子节点,索引段即为B+
    树的非叶子节点。段用来管理多个extent区。
  • :表空间单元结构,每个区的大小为1M。默认情况下,InnoDB存储引擎页大小为16k,即一个区中一共有64个连续的页。
  • :是InnoDB存储引擎磁盘管理的最小单元,每个页的大小默认为16kb。为了保证页的连续性,InnoDB存储引擎每次从磁盘申请4-5个区。
  • :InnoDB存储引擎是按行进行存放的。

InnoDB存储结构

二、InnoDB架构

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

InnoDB架构

2.1 内存结构

2.1.1 Buffer Pool缓冲池

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

缓冲池以page页为单位,底层采用链表数据结构管理page。根据状态page分为三类:

  • 1.free page:空闲页,未被使用。
  • 2.clean page:被使用页,数据没有被修改过。
  • 3.dirty page:脏页,被使用page,数据被修改过,其中数据与磁盘数据产生不一致。

2.1.2 Change Buffer更改缓冲区

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

Change Buffer的意义:
与聚集索引不同,二级索引通常是非唯一的,并且以相对随机的顺序插入二级索引。同样,删除和更新可能会影响索引树中不相邻的二级索引页,
如果每一次都操作磁盘,会造成大量的磁盘IO。有了更改缓冲区后,我们可以在缓存池中进行合并处理,减少磁盘IO。

2.1.3 Adaptive Hash Index自适应哈希索引

Adaptive Hash Index:自适应哈希索引,用于优化对Buffer Pool数据的查询。InnoDB存储引擎会监控对表上各索引页的查询,如果观察到hash索引可以提升速度,
则建立hash索引,称之为自适应hash索引。
自适应哈希索引无需人为干预,是系统根据情况自动完成

查看自适应哈希索引是否打开:
show variables like '%hash_index%';
参数开关:adaptive_hash_index

2.1.4 Log Buffer日志缓冲区

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

参数:
Innodb_log_buffer_size:缓冲区大小
查看缓冲区大小:show variables like '%log_buffer_size%';

innodb_flush_log_at_trx__commit:日志刷新到磁盘时机。
1--日志每次事务提交时写入并刷新到磁盘;0--每秒将日志写入并刷新到磁盘一次;2--日志在每次事务提交后写入,并每秒刷新到磁盘一次
查看刷新时机:show variables like '%flush_log%';

2.2 磁盘结构

  • System Tablespace:系统表空间是更改缓冲区的存储区域。如果表是在系统表空间而不是每个表文件或通用表空间中创建的,
    它也可能包含表和索引数据。
    参数:innodb_data_file_path
  • File-Per-Table Tablespaces:每个表的文件表空间包含单个InnoDB表的数据和索引,并存储在文件系统上的单个数据文件中。
    参数:innodb_file_per_table
  • General Tabelspaces:通用表空间,需要通过create tablespace语法创建通用表空间,在创建表时,可以指定该表空间。
    创建表空间语法:create tablespace 表空间名 add datafile '文件名.ibd' engine=innodb;
    指定表空间:create table ... tablespace 表空间名
  • Undo Tablespace:撤销表空间,MySQL实例在初始化时会自动创建两个默认的undo表空间(undo001,undo002初始大小16M),用于存储undo log日志。
  • Temporary Tablespace:InnoDB使用会话临时表空间和全局临时表空间。存储用户创建的临时表等数据。
  • Doublewrite Buffer Files:双写缓冲区,InnoDB引擎将数据页从Buffer pool刷新到磁盘前,先将数据页写入双写缓冲区文件中,便于系统异常时恢复数据。
  • Redo Log:重做日志,是用来实现事务的持久性。该日志文件由两部分组成:重做日志缓冲(redo log buffer)重做日志文件(redo log)
    前者是在内存中,后者是在磁盘中。当事务提交后会把所有修改信息存到该日志中,用于在刷新脏页到磁盘时,发生错误时,进行数据恢复使用。
    以循环方式写入重做日志文件,涉及两个文件:ib_logfile0和ib_logfile1

2.3 后台线程

将InnoDB存储引擎缓存池中的数据在合适的时机从内存刷新到磁盘文件中。

分类:

  • 1.Master Thread:核心后台线程,负责调度其他线程,还负责将缓存池中的数据异步刷新到磁盘中,保持数据的一致性,
    还包括脏页的刷新、合并插入缓存、undo页的回收。
  • 2.IO Thread:在InnoDB存储引擎中大量使用了AIO来处理IO请求,这样可以极大提高数据库的性能,而IO Thread主要负责这些IO请求的回调。
线程类型 默认个数 职责
read thread 4 负责读操作
write thread 4 负责写操作
log thread 1 负责将日志缓冲区刷新到磁盘
insert buffer thread 1 负责将缓冲区内容刷新到磁盘
  • 3.Purge Thread:主要用于回收事务已经提交的undo log,在事务提交后,undo log可能不用了,就用它回收。
  • 4.Page Cleaner Thread:协助Master Thread刷新脏页到磁盘的线程,可以减轻Master Thread的工作压力,减少阻塞。

三、InnoDB事务原理

3.1 事务

事务是一组操作的集合,是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,既这些操作要么同时成功,要么同时失败

四大特性(ACID):

  • 原子性:事务时不可分割的最小操作单元,要么全部成功或者全部失败
  • 一致性:事务完成时,必须使所有数据都保持一致状态
  • 隔离性:数据库系统提供隔离机制,保证事务在不受外部并发操作影响的独立环境下yunx
  • 持久性:事务一旦提交或回滚,它对数据库中的数据的改变就是永久的


事务的原子性、一致性和持久性是由Redo Log和Undo Log两个日志文件保障的。
隔离性是由InnoDB存储引擎中锁机制和MVCC保障的。

3.2 Redo Log

Redo Log重做日志,记录的是事务提交时数据页的物理修改,是用来实现事务的持久性
该日志由重做日志缓冲(redo log buffer)重做日志文件(redo log file) 两部分组成,前者在内存中,后者在磁盘中
当事务提交之后会把所有修改信息都存到该日志文件中,用于在刷新脏页到磁盘,发生错误时,进行恢复数据恢复使用

3.3 Undo Log

回滚日志,用于记录数据被修改前的信息,作用包含两个:提供回滚和MVCC(多版本并发控制)
undo log和redo log记录物理日志不同,它是逻辑日志。可以认为当删除一条记录时,undo log中会记录一条对应的插入记录,反之依然,当跟新一条记录时,
它记录一条对应相反的跟新记录。当执行回滚时,就可以从undo log中的逻辑记录读取到相应的内容并回滚。
undo log销毁:undo log在事务执行时产生,事务提交时并不会删除undo log,因为这些日志可能还用于MVCC。
undo log存储:undo log采用段的方式进行管理和记录,存放在前面介绍的rollback segment回滚段中,内部包含1024个undo log segment。

四、MVCC多版本并发控制

4.1 基本概念

  • 当前读:读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。对于日常的操作,如:select ...lock in share mode(共享锁),select ...for update、insert、delete(排他锁)都是一种当前读。
  • 快照读:简单的select(不加锁)就是快照读,快照读,读取的时记录数据的可见版本,又可能是历史数据,不加锁,是非阻塞读。
    read committed:每次select都生成一个快照读
    repeatable read:开启事务后第一个select语句才是快照读的地方。
    serialozable:快照读会退化为当前读。
  • MVCC
    全称:Multi-Version Concurrency Control,多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突,快照读为MySQL实现MVCC提供一个非阻塞读功能。MVCC的具体实现原理,还要依赖于数据库记录中:三个隐式字段undo log日志readView

4.2 实现原理

4.2.1 隐藏字段

隐藏字段 含义
DB_TRX_ID 最近修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID
DB_ROLL_PTR 回滚指针,指向这条记录的上一个版本,用于配合undo log,指向上一个版本
DB_ROW_ID 隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段

4.2.2 Undo Log

回滚日志,在insert、update、delete操作的时候产生的便于数据回滚的日志。
insert操作时,产生的undo log日志只在回滚时需要,在事务提交后,可被立刻删除。
update和delete操作时,产生的undo log日志不仅在回滚时需要,在快照时也需要,不会被立刻删除。

4.2.3 Undo Log版本链

UndoLog

不同事务或相同事务对同一条记录进行修改,会导致该记录的undolog生成一条记录版本链表,链表的头部是最新的旧记录,链表尾部是最早的旧记录。

4.2.4 ReadView

ReadView(读视图)是快照读SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃事务(未提交的)ID。

ReadView四个核心字段:

字段 含义
m_ids 当前活跃的事务ID集合
min_trx_id 最小活跃事务ID
max_trx_id 预分配事务ID,当前最大事务ID+1(因为事务ID是自增的)
creator_trx_id ReadView创建者的事务ID

版本链数据访问规则

访问规则

不同隔离级别,生成ReadView时机不同:

  • Read Committed:在事务中每一次执行快照读时生成ReadView。
  • Repeatable Read:仅在事务中第一从执行快照读时生成ReadView,后续复用该ReadView。

4.2.5 原理分析-RC级别

RC隔离级别下,在事务中每一次执行快照读时生成ReadView。(对照版本链数据访问规则分析)

ReadView-RC

4.2.6 原理分析-RR级别

RR隔离级别下,仅在事务中第一次执行快照读时产生ReadView,后续复用该ReadView。(对照版本链数据访问规则分析)

ReadView-RC

谨此笔记,记录过往。凭君阅览,如能收益,莫大奢望。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇