IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> InnoDB引擎架构 -> 正文阅读

[数据结构与算法]InnoDB引擎架构

逻辑存储结构

表空间(ibd文件):一个mysql实例可以对应多个表空间,用于存储记录、索引等数据

段:分为数据段、索引段、回滚段、InnoDB是索引组织表,数据段就是B+树的叶子节点,索引段即为B+树的非叶子节点,段用来管理多个Extent(区)

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

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

行:InnoDB存储引擎是按行进行存放的

Trx_id:每次对某条记录进行改动时,都会把对应事务的ID赋值给 trx_id 隐藏列,也即是最后一次操作事务的ID

Roll_pointer:每次对某条记录进行改动时,都会把旧版本写入到 undo 日志中,然后这个隐藏列就相当于一个指针,可以通过它来找到该记录修改前的信息

架构

内存结构:左内存、右磁盘、中线程

?内存

Buffer Pool:缓冲池

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

没有缓冲区,每一次增删改查操作都回去操作磁盘k空间,就会存在大量磁盘IO,在业务中磁盘IO是随机IO 非常耗费性能

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

????????free page:空闲page,未被使用

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

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

Change Buffer:更改缓冲区

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

作用:每一次操作磁盘会造成大量磁盘IO,有了ChangeBuffer之后,可以在缓冲池中进行合并处理,减少磁盘IO

自适应Hash

用于优化对Buffer Pool数据的查询,InnoDB会监控对表上各索引页的查询,如果发现Hash索引可以提升速度,则创建Hash索引

Log Buffer

日志缓冲区,保存要写入磁盘中的Log日志数据,默认16MB,日志会定期刷新到磁盘中,如果需要更新、插入或删除许多行的事务,增加日志缓冲区大小可以节省磁盘IO

参数: InnoDB_log_buffer_size : 缓冲区大小

InnoDB_flush_log_at_trx_commit:日志刷新到磁盘时机

1:每次事务提交刷新到磁盘

0:每秒日志写入并刷新到磁盘

2:每次事务提交后,并每秒刷新到磁盘

磁盘

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

????????参数设置:innodb_data_file_path

File-Per-Tbale Tablespace:每个表的文件表空间包含单个InnoDB表的数据和索引,并存储在文件系统上的单个数据文件中

????????参数设置:innodb_file_per_table

General Tablespaces:通用表空间,需要通过 create TableSpace 语法创建,创建表时可指定

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

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

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

Redo Log:重做日志,实现事务的持久性,由重做日志缓冲和重做日志文件组成,前者是在内存中,后者在磁盘中,

事务提交后,会把所有修改信息都放到该日志中,用于刷新脏页到磁盘时发生错误,进行数据恢复

后台线程

作用:将InnoDB缓冲池中的数据在合适的时机刷新到磁盘文件中

1.Master Thread

核心后台线程,负责调度其他线程,还负责将缓冲池中的数据异步刷新到磁盘中,保持数据的一致性,还包括脏页的刷新、合并插入缓存、undo页的回收

2.IO Thread

在InnoDB存储引擎中大量使用了AIO来处理IO请求,这样可以极大地提高数据库的性能,而IO Thread主要负责这些IO请求的回调

?3.Purge Thread

主要用于回收事务已经提交了的undo Log,在事务提交之后,undo Log可能不用了,就用它来回收

4.Page Cleaner Thread

协助 Master Thread 刷新脏页到磁盘的线程,它可以减轻Master Thread 的工作压力,减少阻塞

事务原理

概念

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

事务特性ACID

1.原子性(Atomicity) 一个事务必须被视为一个不可分割的最小单元, 整个事务中的所有操作要么全部提交成功, 要么全部失败,对于一个事务来说,不可能只执行其中的一部分操作

2.一致性(Consistency) 如果在执行事务之前数据库是一致的,那么在执行事务之后数据库也还是一致的;

3.隔离性(Isolation) 事务操作之间彼此独立和透明互不影响。事务独立运行。这通常使用锁来实现。 一个事务处理后的结果,影响了其他事务,那么其他事务会撤回。 事务的100%隔离,需要牺牲速度。

4.持久性(Durability) 事务一旦提交,其结果就是永久的。即便发生系统故障,也能恢复。

持久性由redo log保证

Redo Log:重做日志,实现事务的持久性,由重做日志缓冲和重做日志文件组成,前者是在内存中,后者在磁盘中,

事务提交后,会把所有修改信息都放到该日志中,用于刷新脏页到磁盘时发生错误,进行数据恢复

?

原子性由undo log保证

undo log:回滚日志,用于记录数据被修改前的信息,作用包含:提供回滚和MVCC(多版本并发控制)

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

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

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

MVCC

概念

MVCC,全称?Multi-Version Concurrency Control?,即多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突,快照读为MySQL实现MVCC提供了一个非阻塞读功能。MVCC的具体实现还需要依赖于数据库记录中的三个隐式字段、undo log日志、readView

当前读

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

快照读

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

? ? ? ? Read Committed:每次select,都生成一个快照读

? ? ? ? Repeatable Read:开启事务后第一个select语句才是快照读的地方

? ? ? ? Serializable:快照读会退化为当前读

数据库并发场景有三种:

读-读:不存在任何问题,也不需要并发控制
读-写:有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读,幻读,不可重复读
写-写:有线程安全问题,可能会存在更新丢失问题,比如第一类更新丢失,第二类更新丢失


MVCC 带来的好处

多版本并发控制(MVCC)是一种用来解决读-写冲突的无锁并发控制,也就是为事务分配单向增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照。 所以 MVCC 可以为数据库解决以下问题

在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能
同时还可以解决脏读,幻读,不可重复读等事务隔离问题,但不能解决更新丢失问题

隐式字段

每行记录除了我们自定义的字段外,还有数据库隐式定义的 DB_TRX_ID, DB_ROLL_PTR, DB_ROW_ID 等字段

· DB_TRX_ID
????????6 byte,最近修改(修改/插入)事务 ID:记录创建这条记录/最后一次修改该记录的事务 ID
· DB_ROLL_PTR
????????7 byte,回滚指针,指向这条记录的上一个版本(存储于 rollback segment 里)
· DB_ROW_ID
????????6 byte,隐含的自增 ID(隐藏主键),如果数据表没有主键,InnoDB 会自动以DB_ROW_ID产生一个聚簇索引?
·?实际还有一个删除 flag 隐藏字段, 既记录被更新或删除并不代表真的删除,而是删除 flag 变了

如上图,DB_ROW_ID?是数据库默认为该行记录生成的唯一隐式主键,DB_TRX_ID?是当前操作该记录的事务 ID ,而?DB_ROLL_PTR?是一个回滚指针,用于配合 undo日志,指向上一个旧版本?

undo log日志

undo log 主要分为两种:

insert undo log
代表事务在 insert 新记录时产生的 undo log, 只在事务回滚时需要,并且在事务提交后可以被立即丢弃
update undo log
事务在进行 update 或 delete 时产生的 undo log ; 不仅在事务回滚时需要,在快照读时也需要;所以不能随便删除,只有在快速读或事务回滚不涉及该日志时,对应的日志才会被 purge 线程统一清除

purge

从前面的分析可以看出,为了实现 InnoDB 的 MVCC 机制,更新或者删除操作都只是设置一下老记录的 deleted_bit ,并不真正将过时的记录删除。

为了节省磁盘空间,InnoDB 有专门的 purge 线程来清理 deleted_bit 为 true 的记录。为了不影响 MVCC 的正常工作,purge 线程自己也维护了一个read view(这个 read view 相当于系统中最老活跃事务的 read view );如果某个记录的 deleted_bit 为 true ,并且 DB_TRX_ID 相对于 purge 线程的 read view 可见,那么这条记录一定是可以被安全清除的。

Read View视图

Read View 就是事务进行快照读操作的时候生产的读视图 (Read View),在该事务执行的快照读的那一刻,会生成数据库系统当前的一个快照,记录并维护系统当前活跃事务的 ID (当每个事务开启时,都会被分配一个 ID , 这个 ID 是递增的,所以最新的事务,ID 值越大)

所以我们知道 Read View 主要是用来做可见性判断的, 即当我们某个事务执行快照读的时候,对该记录创建一个 Read View 读视图,把它比作条件用来判断当前事务能够看到哪个版本的数据,既可能是当前最新的数据,也有可能是该行记录的undo log里面的某个版本的数据。

Read View遵循一个可见性算法,主要是将要被修改的数据的最新记录中的 DB_TRX_ID(即当前事务 ID )取出来,与系统当前其他活跃事务的 ID 去对比(由 Read View 维护),如果 DB_TRX_ID 跟 Read View 的属性做了某些比较,不符合可见性,那就通过 DB_ROLL_PTR 回滚指针去取出 Undo Log 中的 DB_TRX_ID 再比较,即遍历链表的 DB_TRX_ID(从链首到链尾,即从最近的一次修改查起),直到找到满足特定条件的 DB_TRX_ID , 那么这个 DB_TRX_ID 所在的旧记录就是当前事务能看见的最新老版本

?

?

?

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-02-28 15:50:37  更:2022-02-28 15:51:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 16:53:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码