【转】2.2【MySQL】运行原理(二):InnoDB 内存结构、磁盘结构及update sql执行过程分析
前一篇讲完了查询流程,我们是不是再讲讲更新流程、插入流程和删除流程?在数据库里面,我们说的update操作其实包括了更新、插入和删除。如果大家有看过MyBatis的源码,应该知道Executor里面也只有doQuery()和doUpdate()的方法,没有doDelete()和doInsert()。
更新流程和查询流程有什么不同呢?基本流程也是一致的,也就是说,它也要经过解析器、优化器的处理,最后交给执行器。区别就在于拿到符合条件的数据之后的操作。
缓冲池 Buffer Pool
首先,InnnoDB的数据都是放在磁盘上的,InnoDB操作数据有一个最小的逻辑单位,叫做页(索引页和数据页)。我们对于数据的操作,不是每次都直接操作磁盘,因为磁盘的速度太慢了。 InnoDB使用了一种缓冲池的技术,也就是把磁盘读到的页放到一块内存区域里面。这个内存区域就叫Buffer Pool。
下一次读取相同的页,先判断是不是在缓冲池里面,如果是,就直接读取,不用再次访问磁盘。
修改数据的时候,先修改缓冲池里面的页。内存的数据页和磁盘数据不一致的时候,我们把它叫做脏页。InnoDB里面有专门的后台线程把Buffer Pool的数据写入到磁盘,每隔一段时间就一次性地把多个修改写入磁盘,这个动作就叫做刷脏。
BufferPool是InnoDB里面非常重要的一个结构,它的内部又分成几块区域。这里我们趁机到官网来认识一下InnoDB的内存结构和磁盘结构。
1.Innodb 内存结构
Innodb的内存结构主要分为 3 个部分: Buffer Pool、Change Buffer、Adaptive HashIndex,另外还有一个(redo)log buffer。
1.1 Buffer Pool
Buffer Pool缓存的是页面信息,包括数据页、索引页。
SHOW STATUS LIKE '%innodb_buffer_pool%'; -- 查看服务器状态中 Buffer Pool 相关信息
SHOW VARIABLES like '%innodb_buffer_pool%'; -- 查看参数(系统变量)
这些状态都可以在官网查到详细的含义,用搜索功能。 Buffer Pool默认大小是128M(134217728字节),可以调整。
内存的缓冲池写满了怎么办?(Redis 设置的内存满了怎么办?)InnoDB 用 LRU算法来管理缓冲池(链表实现,不是传统的LRU,分成了young和old),经过淘汰的数据就是热点数据。
1.2 Change Buffer(写缓冲)
什么时候发生 merge?有几种情况:在访问这个数据页的时候,或者通过后台线程、或者数据库shut down、redo log写满时触发。
如果数据库大部分索引都是非唯一索引,并且业务是写多读少,不会在写数据后立刻读取,就可以使用Change Buffer(写缓冲)。写多读少的业务,调大这个值:
SHOW VARIABLES LIKE 'innodb_change_buffer_max_size';
max_size 代表Change Buffer占Buffer Pool的比例,默认25%。
1.3 Adaptive Hash Index
索引应该是放在磁盘的,为什么要专门把一种哈希的索引放到内存?这里就不说了,把问题的答案放在详谈索引存储结构推演过程…
1.4 Log Buffer(Redo log)
这种日志和磁盘配合的整个过程,其实就是 MySQL 里的 WAL 技术(Write-Ahead Logging),它的关键点就是先写日志,再写磁盘。
我们先来了解一下随机I/O和顺序I/O的概念。磁盘的最小组成单元是扇区,通常是512个字节。操作系统和内存打交道,最小的单位是页Page。操作系统和磁盘打交道,读写磁盘,最小的单位是块Block。
假设我们已经找到了第一块数据,并且其他所需的数据就在这一块数据后边,那么就不需要重新寻址,可以依次拿到我们所需的数据,这个就叫顺序IO。
redo log是InnoDB存储引擎实现的,并不是所有存储引擎都有。
不是记录数据页更新之后的状态(某一行或某几行修改成怎样怎样),而是记录当前页做了什么改动,属于物理日志。它用来恢复提交后的物理数据页(恢复数据页,且只能恢复到最后一次提交的位置)
日志分为物理日志和逻辑日志。
- 物理日志就是直接记录数据,记录被修改的page的偏移量,优点就是不依赖原page的内容,用日志的内容可以直接覆盖到磁盘上面,而缺点就是占用的空间太多,比如新增一个btree索引或者一个update操作。
- 逻辑日志只是记录关系表上面的元操作,比如update一行数据,delete一行数据等,优点就是比较简洁而且占用的空间要小,缺点就是需要依赖原page内容,而且会有部分执行和操作一致性的问题。
redo log 分成内存和磁盘两部分:
- 内存部分:Log Buffer,存在刷盘操作。
- 磁盘部分:对应于 /var/lib/mysql/目录下的ib_logfile0和ib_logfile1,每个48M。
因为redo log 实际上记录数据页的变更,而这种变更记录是没必要全部保存,所以 redo log 的大小是固定的,前面的内容会被覆盖。如下图所示:
再强调一次,redo log的内容主要是用于崩溃恢复。磁盘的数据文件,数据来自 buffer pool。redo log 写入磁盘,不是写入数据文件。
redo log 的内存部分:Log Buffer
当然redo log也不是每一次都直接写入磁盘,在Buffer Pool里面有一块内存区域(Log Buffer)专门用来保存即将要写入日志文件的数据,Innodb_log_buffer默认大小为8M,它一样可以节省磁盘IO。
SHOW VARIABLES LIKE 'innodb_log_buffer_size';
那么,Log Buffer什么时候写入log file,或者说什么日志什么时候刷盘?
在我们写入数据到磁盘的时候,操作系统本身是有缓存的。flush就是把操作系统缓冲区写入到磁盘。log buffer写入磁盘的时机,由一个参数控制,默认是1。
值 | 含义 |
---|---|
0(延迟写) | logbuffer 将每秒一次地写入 logfile 中,并且 logfile 的 flush 操作同时进行。 该模式下,在事务提交的时候,不会主动触发写入磁盘的操作。 |
1(默认,实时写,实时刷) | 每次事务提交时 MySQL 都会把 logbuffer 的数据写入 logfile,并且刷到磁盘中去。 |
2(实时写,延迟刷) | 每次事务提交时 MySQL 都会把 logbuffer 的数据写入 logfile。但是 flush 操作并不会同时进行。该模式下,MySQL 会每秒执行一次 flush 操作。 |
SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';
以上就是MySQL的内存结构。总结一下,分为:Buffer pool、change buffer、Adaptive Hash Index、 log buffer。
2.Innodb 磁盘结构(表空间)
磁盘结构里面主要是各种各样的表空间,叫做Table space。表空间可以看做是 InnoDB 存储引擎逻辑结构的最高层,所有的数据都存放在表空间中。InnoDB的表空间分为5大类。
2.1 system tablespace(系统表空间)
在默认情况下 InnoDB 存储引擎有一个共享表空间(对应文件/var/lib/mysql/ibdata1),也叫系统表空间。
InnoDB系统表空间包含InnoDB数据字典和双写缓冲区,ChangeBuffer和UndoLogs),如果没有指定file-per-table,也包含用户创建的表和索引数据。
- undo在后面介绍,因为有独立的表空间。
- 数据字典:由内部系统表组成,存储表和索引的元数据(定义信息)。
- 双写缓冲(InnoDB的一大特性):InnoDB的页和操作系统的页大小不一致,InnoDB页大小一般为16K,操作系统页大小为4K,InnoDB的页写入到磁盘时,一个页需要分4次写。
如果存储引擎正在写入页的数据到磁盘时发生了宕机,可能出现页只写了一部分的情况,比如只写了4K,就宕机了,这种情况叫做部分写失效(partial page write),可能会导致数据丢失。
show variables like 'innodb_doublewrite';
2.2 file-per-table tablespaces(独占表空间)
我们可以让每张表独占一个表空间。这个开关通过innodb_file_per_table设置,默认开启。
SHOW VARIABLES LIKE 'innodb_file_per_table';
开启后,则每张表会开辟一个表空间,这个文件就是数据目录下的 ibd文件(例如
/var/lib/mysql/forum/user_innodb.ibd),存放表的索引和数据。
但是其他类的数据,如回滚(undo)信息,插入缓冲索引页、系统事务信息,二次写缓冲(Double write buffer)等还是存放在原来的共享表空间内。
2.3 general tablespaces(通用表空间)
通用表空间也是一种共享的表空间,跟ibdata1类似。可以创建一个通用的表空间,用来存储不同数据库的表,数据路径和文件可以自定义。语法:
create table space ts2673 add datafile '/var/lib/mysql/ts2673.ibd' file_block_size=16K engine=innodb;
在创建表的时候可以指定表空间,用ALTER修改表空间可以转移表空间。
create table t2673(idinteger) tablespace ts2673;
不同表空间的数据是可以移动的。删除表空间需要先删除里面的所有表:
drop table t2673;
drop tablespace ts2673;
2.4 temporary tablespaces(临时表空间)
存储临时表的数据,包括用户创建的临时表,和磁盘的内部临时表。对应数据目录下的ibtmp1文件。当数据服务器正常关闭时,该表空间被删除,下次重新产生。
2.5 undo log tablespace
redo Log 和 undo Log 与事务密切相关,统称为事务日志。但与redo log不同的是:
undo 是在事务开始之前保存的被修改数据的一个版本,产生undo日志的时候,同样会伴随类似于保护事务持久化机制的 redo log 的产生。
- Redo 记录某 数据块 被修改 后 的值,可以用来恢复未写入 data file 的已成功事务更新的数据。-- 保证事务持久性
- Undo 记录某 数据 被修改 前 的值,可以用来在事务失败时进行 rollback;-- 保证事务原子性
比如某一时刻数据库 DOWN 机了,有两个事务,一个事务已经提交,另一个事务正在处理。数据库重启的时候就要根据日志进行前滚及回滚,把已提交事务的更改写到数据文件,未提交事务的更改恢复到事务开始前的状态。
- 当数据 crash-recovery 时,通过 redo log 将所有已经在存储引擎内部提交的事务应用 redo log 恢复
- 所有已经 prepared 但是没有 commit 的 transactions 将会应用 undo log 做 roll back
undo Log 的数据默认在系统表空间ibdata1 文件中,因为共享表空间不会自动收缩,也可以单独创建一个undo表空间。
==>update过程分析
有了这些日志之后,我们来总结一下一个更新操作的流程,这是一个简化的过程(name原值是zhangsan)。
update user set name='penyuyan' where id=1;
1. 事务开始,从内存或磁盘取到这条数据,返回给Server 的执行器;
2. 执行器修改这一行数据的值为penyuyan;
3. 记录 name=zhangsan 到 undo log;
4. 记录 name=penyuyan 到 redo log;
5. 调用存储引擎接口,在内存(Buffer Pool)中修改 name=zhangsan;
6. 事务提交
另外,内存和磁盘之间,工作着很多后台线程。后台线程的主要作用是负责刷新内存池中的数据和把修改的数据页刷新到磁盘。后台线程分为:master thread,IO thread,purge thread,page cleaner thread。
- master thread:负责刷新缓存数据到磁盘并协调调度其它后台进程
- IO thread:分为 insert buffer、 log、 read、 write进程。分别用来处理 insert buffer、重做日志、读写请求的IO回调
- purge thread:用来回收undo 页
- page cleaner thread:用来刷新脏页
除了 InnoDB 架构中的日志文件,MySQL 的 Server 层也有一个日志文件,叫做binlog,它可以被所有的存储引擎使用。
binlog 以事件的形式记录了所有的DDL和DML语句(因为它记录的是操作而不是数据值,属于逻辑日志),可以用来做主从复制和数据恢复。跟redo log不一样,它的文件内容是可以追加的,没有固定大小限制。
在开启了binlog功能的情况下,我们可以把binlog导出成SQL语句,把所有的操作重放一遍,来实现数据的恢复。binlog的另一个功能就是用来实现主从复制,它的原理就是从服务器读取主服务器的binlog,然后执行一遍。
参考链接:对比总结三大日志:重做日志(redo log),回滚日志(undo log),二进制日志(binlog)
有了这两个日志之后,我们来看一下一条更新语句是怎么执行的:
update teacher set name='盆鱼宴' where id=1
1. 先查询到这条数据,如果有缓存,也会用到缓存。
2. 把name改成盆鱼宴,然后调用引擎的API接口,写入这一行数据到内存,同时记录redo log。这时 redo log 进入prepare 状态,然后告诉执行器,执行完成了,可以随时提交。
3. 执行器收到通知后记录binlog,然后调用存储引擎接口, 设置redolog为commit状态。
4. 更新完成。
需要特别注意的几点:
- 先记录到内存,再写日志文件。
- 记录redo log分为两个阶段。
- 存储引擎和Server记录不同的日志,先记录redo,再记录binlog。
总结脑图
【转】2.2【MySQL】运行原理(二):InnoDB 内存结构、磁盘结构及update sql执行过程分析相关推荐
- MySQL的MyISAM和InnoDB存储引擎表结构
MySQL的MyISAM和InnoDB存储引擎表结构: MyISAM存储引擎: MyISAM表:每一个表都有3个文件,都位于数据库目录中. tb_name.frm 表结构定义 tb_name.MYD ...
- 9.JSP运行原理与JSP页面的基本结构
JSP运行原理与JSP页面的基本结构 HTML页面的基本构成 .代码中出现的几种标签 •单标签 某些标签只需单独使用就能完整地表达意思,控制网页 效果,这类标签的语法是: <标签> ...
- Mysql复习计划(一)- 字符集、文件系统和SQL执行流程
Mysql复习计划(一)- 字符集.文件系统和SQL执行流程 前言 一. Mysql字符集 1.1 Mysql5.7和8.0的默认字符集 1.1.1 修改默认的字符集 1.1.2 修改已有库表的字符集 ...
- 图解 mysql 运行原理
目录 一.逻辑架构图 二.Connectors 三.Management Serveices Utilities 四.Connection Pool 连接池 五.SQL Interface SQL接口 ...
- MyBatis运行原理(二)SqlSession对象创建过程分析
PS:这篇博文承接上一篇: MyBatis运行原理(一)SqlSessionFactory对象创建过程分析 在上一篇博文中分析了SqlSessionFactory对象创建的过程,有了SqlSessio ...
- MySQL索引原理及BTree(B-/+Tree)结构详解
目录 摘要 数据结构及算法基础 索引的本质 B-Tree和B+Tree B-Tree B+Tree 带有顺序访问指针的B+Tree 为什么使用B-Tree(B+Tree) 主存存取原理 磁盘存取原理 ...
- 【Java 虚拟机原理】JDK 体系结构 | Java 源码运行原理 | Java 虚拟机内存
文章目录 一.JDK 体系结构 二.Java 源码运行原理 三.Java 虚拟机内存结构 一.JDK 体系结构 JDK 体系结构 : 下图所有的内容都是 JDK 体系中的组成元素 ; Java Lan ...
- mybatis mysql 调用存储过程 多个返回值_图解MyBatis的SQL执行流程(干货)
前言 MyBatis可能很多人都一直在用,但是MyBatis的SQL执行流程可能并不是所有人都清楚了,那么既然进来了,通读本文你将收获如下: 1.Mapper接口和映射文件是如何进行绑定的 2.MyB ...
- MySQL再叙(体系结构、存储引擎、索引、SQL执行过程)
文章目录 体系结构 存储引擎 SQL执行过程 select的执行过程 update的执行过程 索引 小结 提起MySQL,大家一定不陌生,MySQL是最流行的关系型数据库管理系统,MySQL的历史可以 ...
最新文章
- pip install nmslib 失败 (error: command ‘x86_64-linux-gnu-gcc‘ failed with exit status 1)
- 数造未来——探索大数据的应用价值
- [转载]静态构造函数
- Gallery简单应用
- java dumpstack_Java获取执行进程的dump文件及获取Java stack
- 500位全球算法开发者零奖金参加阿里云天池大赛 AI预测台风助力防灾减灾
- php命名空间更麻烦了,紧急求教PHP命名空间问题,12:10了我还没有吃饭呢,各位帮忙!!...
- 详细分析谷歌紧急修复的 Chrome 0day(CVE-2021-21224)
- ubuntu vscode通过cmake配置c++和VS2019一样 进行调试
- 02-橄榄球 VS 软件
- 分布式事务之基础概念篇
- 计算机组成原理白中英知识点总结,计算机组成原理重点整理(白中英版)
- 冒险岛079服务端_linux版(ubuntu,CentOS)下载
- Ubuntu 14.04 安装TM2009/QQ
- Win 开机自动启动 WSL 服务
- WMB Compute 节点访问数据库
- 在京东工作是一种什么样的体验
- 从200K/s到2M/s,只差这篇文章——使用ProxyeeDown加速百度云盘下载速度
- CIPP非开挖修复技术|UV紫外光与传统水翻CIPP修复对比分析
- OSPFv2原理详解(基于RFC2328)+配置介绍+RFC2328翻译