Skip to content

Commit dd6016c

Browse files
committed
📚mysql
1 parent 2bb0318 commit dd6016c

File tree

96 files changed

+6204
-6022
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+6204
-6022
lines changed

docs/.DS_Store

0 Bytes
Binary file not shown.

docs/.vuepress/config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,8 @@ function genDataManagementSidebar(){
221221
['MySQL/MySQL-Transaction', 'MySQL 事务'],
222222
['MySQL/MySQL-Log', 'MySQL 日志'],
223223
['MySQL/MySQL-Lock', 'MySQL 锁'],
224-
['MySQL/MySQL-select', 'MySQL 查询'],
225-
['MySQL/数据库三范式', '数据库三范式'],
224+
['MySQL/MySQL-Select', 'MySQL 查询'],
225+
// ['MySQL/数据库三范式', '数据库三范式'],
226226
]
227227
},
228228
{

docs/_images/.DS_Store

0 Bytes
Binary file not shown.

docs/_images/mysql/.DS_Store

0 Bytes
Binary file not shown.
-116 KB
Binary file not shown.
-155 KB
Binary file not shown.
-423 KB
Binary file not shown.

docs/data-management/.DS_Store

0 Bytes
Binary file not shown.

docs/data-management/MySQL/MySQL-Split.md

Whitespace-only changes.

docs/data-management/MySQL/MySQL-Storage-Engines.md

Lines changed: 66 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1-
# Mysql Storage Engines
1+
---
2+
title: Mysql Storage Engines
3+
date: 2023-05-31
4+
tags:
5+
- MySQL
6+
categories: MySQL
7+
---
28

39
存储引擎是 MySQL 的组件,用于处理不同表类型的 SQL 操作。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能,使用不同的存储引擎,还可以获得特定的功能。
410

511
使用哪一种引擎可以灵活选择,**<font color=red>一个数据库中多个表可以使用不同引擎以满足各种性能和实际需求</font>**,使用合适的存储引擎,将会提高整个数据库的性能 。
612

7-
MySQL服务器使用可插拔的存储引擎体系结构,可以从运行中的MySQL服务器加载或卸载存储引擎 。
13+
MySQL 服务器使用可插拔的存储引擎体系结构,可以从运行中的MySQL服务器加载或卸载存储引擎 。
814

915
> [MySQL 5.7 可供选择的存储引擎](https://dev.mysql.com/doc/refman/5.7/en/storage-engines.html)
1016
@@ -25,7 +31,19 @@ show table status like 'tablename'
2531
show table status from database where name="tablename"
2632
```
2733

28-
![mysql-engines](https://img.starfish.ink/mysql/mysql-engines.png)
34+
![](https://img.starfish.ink/mysql/mysql-engines.png)
35+
36+
> | 存储引擎 | 描述 |
37+
> | ----------- | ------------------------------------ |
38+
> | `ARCHIVE` | 用于数据存档(行被插入后不能再修改) |
39+
> | `BLACKHOLE` | 丢弃写操作,读操作会返回空内容 |
40+
> | `CSV` | 在存储数据时,以逗号分隔各个数据项 |
41+
> | `FEDERATED` | 用来访问远程表 |
42+
> | `InnoDB` | 具备外键支持功能的事务存储引擎 |
43+
> | `MEMORY` | 置于内存的表 |
44+
> | `MERGE` | 用来管理多个MyISAM表构成的表集合 |
45+
> | `MyISAM` | 主要的非事务处理存储引擎 |
46+
> | `NDB` | MySQL集群专用存储引擎 |
2947
3048

3149

@@ -158,34 +176,20 @@ SET default_storage_engine=NDBCLUSTER;
158176

159177
在 InnoDB 存储引擎中,所有的数据都被逻辑地存放在表空间中,表空间(tablespace)是存储引擎中最高的存储逻辑单位,在表空间的下面又包括段(segment)、区(extent)、页(page)
160178

161-
![tablespace-segment-extent-page-row](../../_images/mysql/tablespace-segment-extent-page-row.jpg)
179+
![](https://img.starfish.ink/mysql/table-space.jpg)
162180

163181
同一个数据库实例的所有表空间都有相同的页大小;默认情况下,表空间中的页大小都为 16KB,当然也可以通过改变 `innodb_page_size` 选项对默认大小进行修改,需要注意的是不同的页大小最终也会导致区大小的不同
164182

165-
![img](https://oss-emcsprod-public.modb.pro/wechatSpider/modb_20210809_11aefc96-f8bc-11eb-b9b6-00163e068ecd.png)
166-
167-
从图中可以看出,在 InnoDB 存储引擎中,一个区的大小最小为 1MB,页的数量最少为 64 个。
168-
169183

170184

171185
#### 如何存储表
172186

173-
MySQL 使用 InnoDB 存储表时,会将表的定义和数据索引等信息分开存储,其中前者存储在 `.frm` 文件中,后者存储在 `.ibd` 文件中,这一节就会对这两种不同的文件分别进行介绍。
174-
175-
![frm-and-ibd-file](https://raw.githubusercontent.com/Draveness/Analyze/master/contents/Database/images/mysql/frm-and-ibd-file.jpg)
187+
MySQL 使用 InnoDB 存储表时,会将表的定义和数据索引等信息分开存储,其中前者存储在 `.frm` 文件中,后者存储在 `.ibd` 文件中。
176188

177189
#### .frm 文件
178190

179191
无论在 MySQL 中选择了哪个存储引擎,所有的 MySQL 表都会在硬盘上创建一个 `.frm` 文件用来描述表的格式或者说定义;`.frm` 文件的格式在不同的平台上都是相同的。
180192

181-
```mysql
182-
`CREATE TABLE test_frm(`` ``column1 CHAR(5),`` ``column2 INTEGER``);`
183-
```
184-
185-
当我们使用上面的代码创建表时,会在磁盘上的 `datadir` 文件夹中生成一个 `test_frm.frm` 的文件,这个文件中就包含了表结构相关的信息:
186-
187-
![frm-file-hex](../../_images/mysql/frm-file-hex.png)
188-
189193
> MySQL 官方文档中的 [11.1 MySQL .frm File Format](https://dev.mysql.com/doc/internals/en/frm-file-format.html) 一文对于 `.frm` 文件格式中的二进制的内容有着非常详细的表述。
190194
191195
#### .ibd 文件
@@ -194,53 +198,72 @@ InnoDB 中用于存储数据的文件总共有两个部分,一是系统表空
194198

195199
当打开 `innodb_file_per_table` 选项时,`.ibd` 文件就是每一个表独有的表空间,文件存储了当前表的数据和相关的索引数据。
196200

197-
#### 如何存储记录
201+
#### 如何存储记录 | InnoDB 行格式
198202

199-
与现有的大多数存储引擎一样,InnoDB 使用页作为磁盘管理的最小单位;数据在 InnoDB 存储引擎中都是按行存储的,每个 16KB 大小的页中可以存放 2-7992 行的记录。(至少是2条记录,最多是7992条记录)
203+
InnoDB 存储引擎和大多数数据库一样,记录是以行的形式存储的,每个 16KB 大小的页中可以存放 2-200 条行记录。
200204

201-
当 InnoDB 存储数据时,它可以使用不同的行格式进行存储;MySQL 5.7 版本支持以下格式的行存储方式:
205+
它可以使用不同的行格式进行存储
202206

203-
![Antelope-Barracuda-Row-Format](../../_images/mysql/Antelope-Barracuda-Row-Format.jpg)
207+
InnoDB 早期的文件格式为 `Antelope`,可以定义两种行记录格式,分别是 `Compact``Redundant`,InnoDB 1.0.x 版本开始引入了新的文件格式 `Barracuda``Barracuda `文件格式下拥有两种新的行记录格式:`Compressed``Dynamic`
204208

205-
Antelope 是 InnoDB 最开始支持的文件格式,它包含两种行格式 Compact 和 Redundant,它最开始并没有名字;Antelope 的名字是在新的文件格式 Barracuda 出现后才起的,Barracuda 的出现引入了两种新的行格式 Compressed 和 Dynamic;InnoDB 对于文件格式都会向前兼容,而官方文档中也对之后会出现的新文件格式预先定义好了名字:Cheetah、Dragon、Elk 等等。
209+
> [InnoDB Row Formats](https://dev.mysql.com/doc/refman/5.7/en/innodb-row-format.html#innodb-row-format-redundant)
206210
207-
两种行记录格式 Compact 和 Redundant 在磁盘上按照以下方式存储:
211+
![](https://img.starfish.ink/mysql/innodb-row-format.png)
208212

209-
![COMPACT-And-REDUNDANT-Row-Format](../../_images/mysql/COMPACT-And-REDUNDANT-Row-Format.jpg)
213+
> ???? 与现有的大多数存储引擎一样,InnoDB 使用页作为磁盘管理的最小单位;数据在 InnoDB 存储引擎中都是按行存储的,每个 16KB 大小的页中可以存放 2-7992 行的记录。(至少是2条记录,最多是7992条记录)
210214
211-
Compact 和 Redundant 格式最大的不同就是记录格式的第一个部分;在 Compact 中,行记录的第一部分倒序存放了一行数据中列的长度(Length),而 Redundant 中存的是每一列的偏移量(Offset),从总体上看,Compact 行记录格式相比 Redundant 格式能够减少 20% 的存储空间。
215+
MySQL 5.7 版本支持以下格式的行存储方式:
212216

213-
#### 行溢出数据
217+
```mysql
218+
CREATE TABLE 表名 (列的信息) ROW_FORMAT=行格式名称
219+
220+
ALTER TABLE 表名 ROW_FORMAT=行格式名称
221+
```
214222

215-
当 InnoDB 使用 Compact 或者 Redundant 格式存储极长的 VARCHAR 或者 BLOB 这类大对象时,我们并不会直接将所有的内容都存放在数据页节点中,而是将行数据中的前 768 个字节存储在数据页中,后面会通过偏移量指向溢出页。
223+
`Compact`行记录格式是在 MySQL 5.0 中引入的,其首部是一个非 NULL 变长列长度列表,并且是逆序放置的,其长度为:
216224

217-
![Row-Overflo](../../_images/mysql/Row-Overflow.jpg)
225+
- 若列的长度小于等于 255 字节,用 1 个字节表示;
226+
- 若列的长度大于 255 字节,用 2 个字节表示。
218227

219-
但是当我们使用新的行记录格式 Compressed 或者 Dynamic 时都只会在行记录中保存 20 个字节的指针,实际的数据都会存放在溢出页面中
228+
变长字段的长度最大不可以超过 2 字节,这是因为 MySQL 数据库中 VARCHAR 类型的最大长度限制为 65535。变长字段之后的第二个部分是 NULL 标志位,该标志位指示了该行数据中某列是否为 NULL 值,有则用 1 表示,NULL 标志位也是不定长的。接下来是记录头部信息,固定占用 5 字节
220229

221-
![Row-Overflow-in-Barracuda](../../_images/mysql/Row-Overflow-in-Barracuda.jpg)
230+
`Redundant`是 MySQL 5.0 版本之前 InnoDB 的行记录格式,`Redundant`行记录格式的首部是每一列长度偏移列表,同样是逆序存放的。从整体上看,`Compact`格式的存储空间减少了约 20%,但代价是某些操作会增加 CPU 的使用。
222231

223-
当然在实际存储中,可能会对不同长度的 TEXT 和 BLOB 列进行优化,不过这就不是本文关注的重点了
232+
`Dynamic``Compressed``Compact`行记录格式的变种,`Compressed`会对存储在其中的行数据会以`zlib`的算法进行压缩,因此对于 BLOB、TEXT、VARCHAR 这类大长度类型的数据能够进行非常有效的存储
224233

225-
> 想要了解更多与 InnoDB 存储引擎中记录的数据格式的相关信息,可以阅读 [InnoDB Record Structure](https://dev.mysql.com/doc/internals/en/innodb-record-structure.html)
226234

227-
#### 数据页结构
228235

229-
页是 InnoDB 存储引擎管理数据的最小磁盘单位,而 B-Tree 节点就是实际存放表中数据的页面,我们在这里将要介绍页是如何组织和存储记录的;首先,一个 InnoDB 页有以下七个部分:
236+
#### 行溢出数据
237+
238+
当 InnoDB 存储极长的 TEXT 或者 BLOB 这类大对象时,MySQL 并不会直接将所有的内容都存放在数据页中。因为 InnoDB 存储引擎使用 B+Tree 组织索引,每个页中至少应该有两条行记录,因此,如果页中只能存放下一条记录,那么InnoDB存储引擎会自动将行数据存放到溢出页中。
230239

231-
![InnoDB-B-Tree-Node](../../_images/mysql/InnoDB-B-Tree-Node.jpg)
240+
如果我们使用`Compact``Redundant`格式,那么会将行数据中的前 768 个字节存储在数据页中,后面的数据会通过指针指向 Uncompressed BLOB Page。
241+
242+
但是如果我们使用新的行记录格式`Compressed` 或者`Dynamic`时只会在行记录中保存 20 个字节的指针,实际的数据都会存放在溢出页面中。
243+
244+
245+
246+
#### 数据页结构
232247

233-
每一个页中包含了两对 header/trailer:内部的 Page Header/Page Directory 关心的是页的状态信息,而 Fil Header/Fil Trailer 关心的是记录页的头信息
248+
页是 InnoDB 存储引擎管理数据的最小磁盘单位,一个页的大小一般是`16KB`
234249

235-
在页的头部和尾部之间就是用户记录和空闲空间了,每一个数据页中都包含 Infimum 和 Supremum 这两个虚拟的记录(可以理解为占位符),Infimum 记录是比该页中任何主键值都要小的值,Supremum 是该页中的最大值:
250+
`InnoDB`为了不同的目的而设计了许多种不同类型的``,比如存放表空间头部信息的页,存放`Insert Buffer`信息的页,存放`INODE`信息的页,存放`undo`日志信息的页等等等等。
236251

237-
![Infimum-Rows-Supremum](../../_images/mysql/Infimum-Rows-Supremum.jpg)
252+
B-Tree 节点就是实际存放表中数据的页面,我们在这里将要介绍页是如何组织和存储记录的;首先,一个 InnoDB 页有以下七个部分:
238253

239-
User Records 就是整个页面中真正用于存放行记录的部分,而 Free Space 就是空余空间了,它是一个链表的数据结构,为了保证插入和删除的效率,整个页面并不会按照主键顺序对所有记录进行排序,它会自动从左侧向右寻找空白节点进行插入,行记录在物理存储上并不是按照顺序的,它们之间的顺序是由 `next_record` 这一指针控制的。
254+
![](https://img.starfish.ink/mysql/innodb-b-tree-node.jpg)
240255

241-
B+ 树在查找对应的记录时,并不会直接从树中找出对应的行记录,它只能获取记录所在的页,将整个页加载到内存中,再通过 Page Directory 中存储的稀疏索引和 `n_owned``next_record` 属性取出对应的记录,不过因为这一操作是在内存中进行的,所以通常会忽略这部分查找的耗时
256+
有的部分占用的字节数是确定的,有的部分占用的字节数是不确定的
242257

243-
InnoDB 存储引擎中对数据的存储是一个非常复杂的话题,这一节中也只是对表、行记录以及页面的存储进行一定的分析和介绍,虽然作者相信这部分知识对于大部分开发者已经足够了,但是想要真正消化这部分内容还需要很多的努力和实践。
258+
| 名称 | 中文名 | 占用空间大小 | 简单描述 |
259+
| -------------------- | ------------------ | ------------ | ------------------------ |
260+
| `File Header` | 文件头部 | `38`字节 | 页的一些通用信息 |
261+
| `Page Header` | 页面头部 | `56`字节 | 数据页专有的一些信息 |
262+
| `Infimum + Supremum` | 最小记录和最大记录 | `26`字节 | 两个虚拟的行记录 |
263+
| `User Records` | 用户记录 | 不确定 | 实际存储的行记录内容 |
264+
| `Free Space` | 空闲空间 | 不确定 | 页中尚未使用的空间 |
265+
| `Page Directory` | 页面目录 | 不确定 | 页中的某些记录的相对位置 |
266+
| `File Trailer` | 文件尾部 | `8`字节 | 校验页是否完整 |
244267

245268

246269

0 commit comments

Comments
 (0)