MySQL数据库进阶第六篇(InnoDB引擎架构,事务原理,MVCC)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: MySQL数据库进阶第六篇(InnoDB引擎架构,事务原理,MVCC)

本文将带您遍览 InnoDB 存储引擎的内部机制,深入其逻辑存储结构和内存架构,解析页、段、区至行的层级,揭秘索引与数据是如何存放的。深入缓冲池的秘密,发现 InnoDB 如何以 Buffer Pool 为纽带,缓解物理硬盘与内存间的速度差异,保持高效。掌握更改缓冲区的智慧,理解非唯一二级索引背后的故事。嗅探自适应哈希索引和日志缓冲区,探寻其提升查询与事务写入的神奇之处。

文章还展现了 InnoDB 独特的磁盘结构布局,包含一应俱全的系统表空间、表级空间和特有的回滚机制,为数据的持久化与安全性搭建了坚实的基础。揭示了后台线程如何无声地协助数据在内存和磁盘间舞动,以及事务原理的严密逻辑,事务的 ACID 特性在 InnoDB 中如何实现。

最后,本文还深入探讨了 MVCC 的实现原理和细节,通过生动的快照读和 ReadView 机制,让并发控制如丝般顺滑,值得每位数据库爱好者细细品味。

一、InnoDB引擎逻辑储存结构

段,分为数据段、索引段、回滚段,InnoDB是索引组织表,数据段是B+树的非叶子结点,段用来管理多个区

区,表空间的单元结构,每个区大小为1M,默认情况下InnoDB存储引擎页大小为16K,即一个区公共有64个连续的页

页,是InnoDB存储引擎磁盘管理的最小单元,每个页的大小默认为16KB。为了保证页的连续性,每次InnoDB都会向磁盘申请4-5个区

行,InnoDB存储引擎数据是按照行进行存放的

记录中的每一列col1,col2,col3

两个隐藏列

Trx id,最后一次操作该行的事务ID

Roll pointer,每次对改行记录进行改动时,会把旧版本写入undo日志中,该值是指针,通过它可以找到之前没有改动的旧版本

二、架构——内存结构

InnoDB存储引擎基于磁盘文件存储,在物理硬盘和在内存中的速度相差很大,为了尽可能弥补这两者之间的I/O效率的差值,就需要把经常使用的数据加载到缓冲池中,避免每次访问都进行非常慢的且大部分都是随机的磁盘I/O。

在InnoDB的缓冲池中不仅缓存了索引页和数据页,还包含了undo页、插入缓存、自适应哈希索引以及 InnoDB的锁信息等等。

## Buffer Pool缓冲池

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

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

free page:空闲page,未被使用

clean page:被使用page,数据没有被修改过

dirty page:脏页,被使用page,数据被修改过,页中数据与磁盘的数据产生了不一致

## Change Buffer 更改缓冲区(针对于非唯一的二级索引页)

在执行DML(数据 增删改)语句时,如果这些数据Page 没有在Buffer Pool中,不会直接操作磁盘,而会将数据变更存在更改缓冲区 Change Buffer 中,在未来数据被读取时,再将数据合并恢复到Buffer Pool中,再将合并后的数据以一定频率刷新到磁盘中。

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

## Adaptive Hash Index 自适应哈希索引

用于优化对Buffer Pool数据的查询。MySQL的innoDB引擎中虽然没有直接支持 hash索引,但是提供功能,即自适应hash索引。

hash索引对于等值匹配,一般性能高于B+树,因为hash索引一般只需要一次IO即可,而B+树可能需 要几次匹配,所以hash索引的效率要高,但hash索引又不适合做范围查询、模糊匹配等。

因此InnoDB存储引擎会监控对表上各索引页的查询,如果观察到在某条件下hash索引效率更高, 则建立hash索引,称为自适应hash索引。 自适应哈希索引无需人工干预,是系统根据情况自动完成。

## 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: 日志在每次事务提交后写入,并每秒刷新到磁盘一次

三、架构——磁盘结构

磁盘结构

## System Tablespace 系统表空间

是更改缓冲区Change Buffer 的存储区域。如果表在系统表空间而不是每个表文件或通用表空间中创建的,它也可能包含表和索引数据。(在MySQL5.x版本中还包含InnoDB数据字典、undolog等)

## File-Per-Table Tablespaces

每张表的独立表空间,则每个表的文件表空间包含单个InnoDB表的数据和索引 ,并存储在文件系统上的单个数据文件中。 一个.ibd 对应一个表

## General Tablespaces 通用表空间

需要通过 CREATE TABLESPACE 语法创建通用表空间,在创建表时,可以指定该表空间

#创建表空间
CREATE TABLESPACE ts_name ADD DATAFILE 'file_name' ENGINE = engine_name;
#创建表时指定表空间
CREATE TABLE xxx ... TABLESPACE ts_name;
#-----------举例-----------
create tablespace ts_01 add datafile 'mydb01.ibd' engine = innodb;
创建表空间成功后,后续创建表时 可以指定把表创建至该表空间里

## Undo Tablespaces 撤销表空间

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

## Temporary Tablespaces 临时会话表空间

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

## Doublewrite Buffer Files 双写缓冲区

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

## Redo Log 重做日志

用来实现事务的持久性。该日志文件由两部分组成:重做日志缓冲区(redo log buffer)(在内存结构的Log Buffer中)以及 重做日志文件(redo log),前者是在内存中,后者在磁盘中。

当事务提交之后会把所有修改信息存到该日志中,用于在刷新脏页到磁盘 发生错误时,进行数据恢复使用。以循环方式写入重做日志文件,涉及两个文件

四、架构——后台线程

内存中的数据和磁盘的数据 是怎么 写入和读取的呢?后台线程

## Master Thread(核心后台线程):

是MySQL的一个核心后台线程,负责管理和协调其他后台线程的工作,并将缓冲池中的数据异步刷新到磁盘中,保持数据的一致性;脏页的刷新、合并插入缓存、undo页的回收

## IO Thread(读写线程):

异步非阻塞IO 极大地提高数据库的性能,这些线程负责处理InnoDB存储引擎的IO请求,包括读取和写入磁盘上的数据。

## Purge Thread(清理线程):

Purge Thread负责回收已完成提交事务的undo log,将其释放以供后续事务使用。

## Page Cleaner Thread(页清理线程):

该线程负责在InnoDB存储引擎中执行脏页的刷新操作,将脏页写回磁盘,以确保数据的持久性和一致性。协助Master Thread。

五、事务原理

事务:一组操作的集合,要么全部成功,要么全部失败:

事务的四大特性:(ACID)原子性,一致性,隔离性,持久性

A:事务是不可分割的最小操作单元,要么全部成功,要么全部失败

C:事务完成时,必须使所有的数据都保持一致状态

I:数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行

D:事务一旦提交或回滚,它对数据库中的数据的改变就是永久的

持久性:redo log。重做日志

记录事务提交时,对数据页的物理修改,实现事务的持久性

包含两部分:重做日志缓冲(内存结构中的Log Buffer)与 磁盘的重做日志文件,提交后会把所有修改信息保存到该文件中,用于当刷新脏页到磁盘发生错误时 进行数据恢复使用

update/delete执行:

先看内存的BufferPool中有没有该页,如果没有该页则通过后台线程从磁盘中把页读到Buffer Pool

直接操作缓冲区中的数据,该页变成脏页

首先把数据页的物理变化记录在内存中的RodoLogBuffer,commit 事务提交的时候,redologBuffer会直接把数据页变化刷新到磁盘当中,即ib_logfile0,ib_logfile1中

在某个时机 该页以一定频率刷新到磁盘中进行持久化,若此时出错,则可以通过磁盘文件中的redo_log进行数据恢复

若脏页顺利写入磁盘,则redolog文件就不再需要,因此每过一段时间就清理一次redo log日志,是循环性的,不是永久的

日志文件都是追加的,是顺序磁盘I/O,效率比数据在磁盘的随机存取快速的多

WAL 先写日志 Write-Ahead Logging

原子性:undo log。回滚日志

用于记录被修改前的信息,作用包括两个:提供回滚 和 MVCC(多版本并发控制)

undo log 和 redo log 记录的物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undo log会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的 update记录(执行update之前 数据长的样子)。当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚

Undo log 销毁:undo log在事务执行时产生,事务提交时,并不会立即删除undo log,因为这些日志可能还用于MVCC

Undo log 存储:undo log采用段的方式进行管理和记录,存放在段中的rollback segment 回滚段中,内部包含1024个undo log segment

六、MVCC基本概念

当前读:读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。对于我们日常的操作,如:select … lock in share mode(共享锁),select … for update、update、insert、delete(排他锁)都是一种当前读。

客户端1使用select 语句,客户端2使用 update语句进行更新,因为当前隔离级别是可重复读,因此客户端1无法看到客户端2事务对数据的更改

当前读

快照读:简单的select(不加锁)就是快照读,快照读 读取的是记录数据的可见版本,有可能是历史数据, 不加锁,是非阻塞读

Read Committed 读已提交:每次select,都生成一个快照读

Repeatable Read 可重复高读:开启事务后第一个select语句才是快照读的地方。即第一次select查询产生快照读,后面的select查询直接使用前面的快照数据

Serializable 串行化:快照读会退化为当前读,每次读取都需要加锁

MVCC: Multi-Version Concurrency Control,多版本并发控制

维护一个数据的多个版本, 使得读写操作没有冲突,快照读 为MySQL实现MVCC提供了一个非阻塞读功能。MVCC的具体实现 依赖于数据库记录中的三个隐式字段、undo log日志、readView

七、MVCC实现原理

八、undo log日志 回滚日志,版本链

undo log日志 回滚日志

在insert、update、delete的时候产生的便于数据回滚的日志。

当insert的时候,产生的undo log日志只在回滚时需要,在事务提交后,可被立即删除

update、delete时,产生的undo log日志不仅在回滚时需要,在快照读时也需要,不会立即被删除

undo log 版本链

最终不同事务或相同事务对同一条记录进行修改,会导致该记录的undolog生成一条 记录版本链表。

链表的头部是最新的旧记录,链表尾部是最早的旧记录。

那么每次查询的时候,返回哪一个版本的记录呢?ReadView的作用

九、readView 读视图 决定查询读取 的记录

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

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

READ COMMITTED :在事务中每一次执行快照读时生成ReadView

REPEATABLE READ:仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView

在RR隔离级别下,只是在事务中第一次快照读时生成ReadView,后续都是复用该 ReadView,那么既然ReadView都一样, ReadView的版本链匹配规则也一样, 那么最终快照读返 回的结果也是一样的

因此,MVCC的实现原理就是通过 InnoDB表的隐藏字段、UndoLog 版本链、ReadView来实现的。 而MVCC + 锁,则实现了事务的隔离性。 而一致性则是由redolog 与 undolog保证

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
13天前
|
存储 关系型数据库 MySQL
MySQL引擎InnoDB和MyISAM的区别?
InnoDB是MySQL默认的事务型存储引擎,支持事务、行级锁、MVCC、在线热备份等特性,主索引为聚簇索引,适用于高并发、高可靠性的场景。MyISAM设计简单,支持压缩表、空间索引,但不支持事务和行级锁,适合读多写少、不要求事务的场景。
42 9
|
2月前
|
存储 SQL 关系型数据库
MySQL的事务隔离级别
【10月更文挑战第17天】MySQL的事务隔离级别
120 43
|
1月前
|
存储 SQL Apache
Apache Doris 开源最顶级基于MPP架构的高性能实时分析数据库
Apache Doris 是一个基于 MPP 架构的高性能实时分析数据库,以其极高的速度和易用性著称。它支持高并发点查询和复杂分析场景,适用于报表分析、即席查询、数据仓库和数据湖查询加速等。最新发布的 2.0.2 版本在性能、稳定性和多租户支持方面有显著提升。社区活跃,已广泛应用于电商、广告、用户行为分析等领域。
Apache Doris 开源最顶级基于MPP架构的高性能实时分析数据库
|
21天前
|
关系型数据库 MySQL
mysql事务特性
原子性:一个事务内的操作统一成功或失败 一致性:事务前后的数据总量不变 隔离性:事务与事务之间相互不影响 持久性:事务一旦提交发生的改变不可逆
|
1月前
|
缓存 关系型数据库 MySQL
高并发架构系列:数据库主从同步的 3 种方案
本文详解高并发场景下数据库主从同步的三种解决方案:数据主从同步、数据库半同步复制、数据库中间件同步和缓存记录写key同步,旨在帮助解决数据一致性问题。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
高并发架构系列:数据库主从同步的 3 种方案
|
19天前
|
关系型数据库 MySQL 数据库
MySQL事务隔离级别及默认隔离级别的设置
在数据库系统中,事务隔离级别是一个关键的概念,它决定了事务在并发执行时如何相互隔离。MySQL提供了四种事务隔离级别,每种级别都解决了不同的并发问题。本文将详细介绍这些隔离级别以及MySQL的默认隔离级别。
|
2月前
|
存储 关系型数据库 MySQL
mysql 引擎概述
MySQL存储引擎是处理不同类型表操作的组件,InnoDB是最常用的默认引擎,支持事务、行级锁定和外键。MySQL采用插件式存储引擎架构,支持多种引擎,如MyISAM、Memory、CSV等,每种引擎适用于不同的应用场景。通过`SHOW ENGINES`命令可查看当前MySQL实例支持的存储引擎及其状态。选择合适的存储引擎需根据具体业务需求和引擎特性来决定。
|
26天前
|
存储 Cloud Native NoSQL
云原生时代的数据库选型与架构设计
云原生时代的数据库选型与架构设计
23 0
|
12天前
|
弹性计算 API 持续交付
后端服务架构的微服务化转型
本文旨在探讨后端服务从单体架构向微服务架构转型的过程,分析微服务架构的优势和面临的挑战。文章首先介绍单体架构的局限性,然后详细阐述微服务架构的核心概念及其在现代软件开发中的应用。通过对比两种架构,指出微服务化转型的必要性和实施策略。最后,讨论了微服务架构实施过程中可能遇到的问题及解决方案。
|
21天前
|
Cloud Native Devops 云计算
云计算的未来:云原生架构与微服务的革命####
【10月更文挑战第21天】 随着企业数字化转型的加速,云原生技术正迅速成为IT行业的新宠。本文深入探讨了云原生架构的核心理念、关键技术如容器化和微服务的优势,以及如何通过这些技术实现高效、灵活且可扩展的现代应用开发。我们将揭示云原生如何重塑软件开发流程,提升业务敏捷性,并探索其对企业IT架构的深远影响。 ####
34 3