MySQL内部模块连接器(JDBC、ODBC等) =>
[MYSQL 内部
[Connection Pool] (授权、线程复用、连接限制、内存检测等)=>[SQL Interface] (DML、DDL、Views等) [Parser] (Query Translation、Object privilege) [Optimizer] (Access Paths、 统计分析) [Caches & Buffers]=>[Pluggable Storage Engines]复制代码
]
=> [File]
一条SQL执行过程先看看一条查询SQL
文章插图
- (这里提供一下官方对各存储引擎的文档说明 Mysql存储引擎)
Innodb 架构上一张 MYSQL 官方InnoDB架构图:
文章插图
内存结构这里有个关键点,当我们去查询数据时候会先 拿着我们当前查询的 夜 去 缓冲池 中查询 当前页是否在缓冲池中 。如果在,则直接获取 。
当是update时,则会直接修改 Buffer中的值 。这个时候,缓冲池中的数据就和磁盘中存储的数据不一致了,称为网页 。每隔一段时间,Innodb存储引擎就会把脏页数据刷入磁盘 。
一般来说当更新一条数据,我们需要将数据给读取到buffer中修改,然后写回磁盘,其中有一次 IO 操作 。
图中缓冲池中有一块区域叫做:change buffer 。当更新一个没有 unique index 的数据时,直接将修改的数据放到 change buffer,然后通过 merge 操作完成更新,从而减少了 IO 操作 。
- 为什么要没有唯一索引的数据更新时才能这样呢,因为我们更新数据后,可能更新后的数据和已经存在的数据有重复,所以必须从磁盘中把所有数据读出来比对才行 。
- 所以当我们的数据是 写多读少 的时候,就可以通过 增加 innodb_change_buffer_max_size 来调整 change buffer在buffer pool 中所占的比例,默认25(即:25%)
- 有其他访问,访问到了当前页的数据,就会合并到磁盘
- 后台线程定时
- 系统正常shut down之前
- redo log写满的时候
这样就可以在,当数据库崩溃的后,直接从 redo log中恢复数据,保证数据的正确性
- redo log 默认存储在两个文件中 ib_logfile0 ib_logfile1,这两个文件都是固定大小的 。为什么需要固定大小?这是因为redo log的顺序读取的特性造成的,必须是连续的存储空间
文章插图
一般我们的数据都是分散在磁盘上的: 机械硬盘:
- 定位到磁道
- 等待旋转到对应扇区
- 开始读写
- 直接定位到闪存芯片(这也是为啥固态比机械快)
- 开始读写
- 随机读写存储的数据是分布在不同的 块(默认 1block=8扇区=4K)
- 而顺序存储,顾名思义,数据是分布在一串连续的块中,这样读取速度就大大提升了
文章插图
看到buffer pool中的Log Buffer,其就是用来写 redo log 之前存在的缓冲区
在这里,redo log具体的执行策略有三种:
- 不用写Log Buffer,只需要每秒写redo log 磁盘数据一次,性能高,但会造成数据 1s 内的一致性问题 。适用于强实时性,弱一致性,比如评论区评论
- 写Log Buffer,同时写入磁盘,性能最差,一致性最高 。适用于弱实时性,强一致性,比如支付场景
- 写Log Buffer,同时写到os buffer(其会每秒调用 fsync 将数据刷入磁盘),性能好,安全性也高 。这个是实时性适中 一致性适中的,比如订单类 。
内存结构小结
推荐阅读
- 终于搞懂分布式锁是什么了
- 彻底搞懂epoll高效运行的原理
- 一文读懂响应式编程到底是什么?
- 一文带你了解Notta是什么
- 电脑用久了太卡?优化一下磁盘,让你的电脑“快如闪电”
- CPU越来越热吗 一文带你看懂怎么选
- 3大补水法让你冬日皮肤水灵灵
- 一文搞懂 Traefik2.1 的使用
- 护发方法 让你拥有“魅力”秀发的食疗方法
- 失眠吃什么好 18个食疗小偏方让你整夜酣睡