Skip to content

修复 Autocorrect 告警 #336

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cs_learn/cs_learn.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ MySQL 入门的话是了解 SQL 语法,进阶的话是深入底层实现原理
我先介绍下 MySQL 的重点知识,也是面试常面的知识点:

- **基本语法**:select/delete/insert/update、limit、join 等
- **索引**:B+树,聚族索引,二级索引,组合索引,最左匹配原则,索引失效、慢查询
- **索引**:B+ 树,聚族索引,二级索引,组合索引,最左匹配原则,索引失效、慢查询
- **事务**:事务四大特性 ACID,事务隔离级别,MVCC
- **锁**:全局锁、表级锁、行级锁、快照读、当前读、乐观锁、悲观锁、死锁
- **日志**:重做日志 (redo log)、回滚日志 (undo log)、二进制日志 (binlog)
Expand Down Expand Up @@ -370,7 +370,7 @@ Redis 官网也有一整套的命令详解,遇到需要或者不会的地方
所以最好的看书方式是带着问题去翻阅,比如:

- 带着程序是如何在计算机里跑起来的问题,去学计算机组成原理;
- 带着输入一条 url 到网页显示,期间发生了什么的问题,去学习计算机网络;
- 带着输入一条 URL 到网页显示,期间发生了什么的问题,去学习计算机网络;
- 带着进程、内存、磁盘是如何被操作系统管理点,去学习操作系统;
- 带着如何实现一个高并发网络模型,去学习网络编程;
- ……
Expand Down
2 changes: 1 addition & 1 deletion cs_learn/feel_cs.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

![图片](https://img-blog.csdnimg.cn/img_convert/d3692e2197fb0d020ca4f13a4d3a1b42.png)

他从那时起,就日复一日的学习,并在 Github 有做笔记的习惯,你看他的提交记录,每天都有,一天都没拉下,就这样坚持了一年。
他从那时起,就日复一日的学习,并在 GitHub 有做笔记的习惯,你看他的提交记录,每天都有,一天都没拉下,就这样坚持了一年。

这个一年没有间断过的坚持,我是真的被震撼到,虽然我也经常肝文章,但是我也做不到每天都是学习的状态,总会想偷懒几天,毕竟学习真的是反人性的哈哈。

Expand Down
2 changes: 1 addition & 1 deletion cs_learn/look_book.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@

这两本书让我大概知道了如果一个服务端要服务多个客户端时,不是就简单写个 socket 编程就完事,而是还要结合 IO 多路复用 + 多线程的思想,也就是 Reactor 的设计理念,知道了这些事情后,后面我在看很多开源框架的网络模型时候,发现大多数基于 Reactor 的思想来实现的。

有了网络编程总体的视角后,在需要深入理解 socket api 中各种属性设置(超时、非阻塞 IO、阻塞 IO 等)和异常处理就要回归 APUE 这本书。
有了网络编程总体的视角后,在需要深入理解 socket API 中各种属性设置(超时、非阻塞 IO、阻塞 IO 等)和异常处理就要回归 APUE 这本书。

到这里我才知道 UNP 和 APUE 为什么会被称为网络编程圣经级别的书,原因是书里各种细节和异常都写的很全,也很细致,可以应对工作中很多问题。

Expand Down
6 changes: 3 additions & 3 deletions mysql/base/how_select.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ select * from product where id = 1;
可以看到,MySQL 的架构共分为两层:**Server 层和存储引擎层**,

- **Server 层负责建立连接、分析和执行 SQL**。MySQL 大多数的核心功能模块都在这实现,主要包括连接器,查询缓存、解析器、预处理器、优化器、执行器等。另外,所有的内置函数(如日期、时间、数学和加密函数等)和所有跨存储引擎的功能(如存储过程、触发器、视图等。)都在 Server 层实现。
- **存储引擎层负责数据的存储和提取**。支持 InnoDB、MyISAM、Memory 等多个存储引擎,不同的存储引擎共用一个 Server 层。现在最常用的存储引擎是 InnoDB,从 MySQL 5.5 版本开始,InnoDB 成为了 MySQL 的默认存储引擎。我们常说的索引数据结构,就是由存储引擎层实现的,不同的存储引擎支持的索引类型也不相同,比如 InnoDB 支持索引类型是 B+树,且是默认使用,也就是说在数据表中创建的主键索引和二级索引默认使用的是 B+ 树索引。
- **存储引擎层负责数据的存储和提取**+。支持 InnoDB、MyISAM、Memory 等多个存储引擎,不同的存储引擎共用一个 Server 层。现在最常用的存储引擎是 InnoDB,从 MySQL 5.5 版本开始,InnoDB 成为了 MySQL 的默认存储引擎。我们常说的索引数据结构,就是由存储引擎层实现的,不同的存储引擎支持的索引类型也不相同,比如 InnoDB 支持索引类型是 B+ 树,且是默认使用,也就是说在数据表中创建的主键索引和二级索引默认使用的是 B+ 树索引。

好了,现在我们对 Server 层和存储引擎层有了一个简单认识,接下来,就详细说一条 SQL 查询语句的执行流程,依次看看每一个功能模块的作用。

Expand All @@ -31,7 +31,7 @@ select * from product where id = 1;
如果你在 Linux 操作系统里要使用 MySQL,那你第一步肯定是要先连接 MySQL 服务,然后才能执行 SQL 语句,普遍我们都是使用下面这条命令进行连接:

```shell
# -h 指定 MySQL 服务的 IP 地址,如果是连接本地的 MySQL服务,可以不用这个参数;
# -h 指定 MySQL 服务的 IP 地址,如果是连接本地的 MySQL 服务,可以不用这个参数;
# -u 指定用户名,管理员角色名为 root;
# -p 指定密码,如果命令行中不填写密码(为了密码安全,建议不要在命令行写密码),就需要在交互对话里面输入密码
mysql -h$ip -u$user -p
Expand Down Expand Up @@ -273,7 +273,7 @@ select * from product where name = 'iphone';
这条查询语句的查询条件没有用到索引,所以优化器决定选用访问类型为 ALL 进行查询,也就是全表扫描的方式查询,那么这时执行器与存储引擎的执行流程是这样的:

- 执行器第一次查询,会调用 read_first_record 函数指针指向的函数,因为优化器选择的访问类型为 all,这个函数指针被指向为 InnoDB 引擎全扫描的接口,**让存储引擎读取表中的第一条记录**;
- 执行器会判断读到的这条记录的 name 是不是 iphone,如果不是则跳过;如果是则将记录发给客户端(是的没错,Server 层每从存储引擎读到一条记录就会发送给客户端,之所以客户端显示的时候是直接显示所有记录的,是因为客户端是等查询语句查询完成后,才会显示出所有的记录)。
- 执行器会判断读到的这条记录的 name 是不是 `iphone`,如果不是则跳过;如果是则将记录发给客户端(是的没错,Server 层每从存储引擎读到一条记录就会发送给客户端,之所以客户端显示的时候是直接显示所有记录的,是因为客户端是等查询语句查询完成后,才会显示出所有的记录)。
- 执行器查询的过程是一个 while 循环,所以还会再查一次,会调用 read_record 函数指针指向的函数,因为优化器选择的访问类型为 all,read_record 函数指针指向的还是 InnoDB 引擎全扫描的接口,所以接着向存储引擎层要求继续读刚才那条记录的下一条记录,存储引擎把下一条记录取出后就将其返回给执行器(Server 层),执行器继续判断条件,不符合查询条件即跳过该记录,否则发送到客户端;
- 一直重复上述过程,直到存储引擎把表中的所有记录读完,然后向执行器(Server 层)返回了读取完毕的信息;
- 执行器收到存储引擎报告的查询完毕的信息,退出循环,停止查询。
Expand Down
12 changes: 6 additions & 6 deletions mysql/base/row_format.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,8 @@ CREATE TABLE `t_user` (

如果存在允许 NULL 值的列,则每个列对应一个二进制位(bit),二进制位按照列的顺序逆序排列。

- 二进制位的值为`1`时,代表该列的值为 NULL。
- 二进制位的值为`0`时,代表该列的值不为 NULL。
- 二进制位的值为 `1` 时,代表该列的值为 NULL。
- 二进制位的值为 `0` 时,代表该列的值不为 NULL。

另外,NULL 值列表必须用整数个字节的位表示(1 字节 8 位),如果使用的二进制位个数不足整数个字节,则在字节的高位补 `0`。

Expand Down Expand Up @@ -249,7 +249,7 @@ NULL 值列表也不是必须的。

**当数据表的字段都定义成 NOT NULL 的时候,这时候表里的行格式就不会有 NULL 值列表了**。

所以在设计数据库表的时候,通常都是建议将字段设置为 NOT NULL,这样可以至少节省 1 字节的空间(NULL 值列表至少占用 1 字节空间)。
所以在设计数据库表的时候,通常都是建议将字段设置为 NOT NULL,这样可以至少节省 1 字节的空间(NULL 值列表至少占用 1 字节空间)。

> 「NULL 值列表」是固定 1 字节空间吗?如果这样的话,一条记录有 9 个字段值都是 NULL,这时候怎么表示?

Expand All @@ -261,9 +261,9 @@ NULL 值列表也不是必须的。

记录头信息中包含的内容很多,我就不一一列举了,这里说几个比较重要的:

- delete_mask:标识此条数据是否被删除。从这里可以知道,我们执行 detele 删除记录的时候,并不会真正的删除记录,只是将这个记录的 delete_mask 标记为 1。
- next_record:下一条记录的位置。从这里可以知道,记录与记录之间是通过链表组织的。在前面我也提到了,指向的是下一条记录的「记录头信息」和「真实数据」之间的位置,这样的好处是向左读就是记录头信息,向右读就是真实数据,比较方便。
- record_type:表示当前记录的类型,0 表示普通记录,1 表示 B+树非叶子节点记录,2 表示最小记录,3 表示最大记录
- `delete_mask`:标识此条数据是否被删除。从这里可以知道,我们执行 delete 删除记录的时候,并不会真正的删除记录,只是将这个记录的 `delete_mask` 标记为 1。
- `next_record`:下一条记录的位置。从这里可以知道,记录与记录之间是通过链表组织的。在前面我也提到了,指向的是下一条记录的「记录头信息」和「真实数据」之间的位置,这样的好处是向左读就是记录头信息,向右读就是真实数据,比较方便。
- `record_type`:表示当前记录的类型,0 表示普通记录,1 表示 B+ 树非叶子节点记录,2 表示最小记录,3 表示最大记录

### 记录的真实数据

Expand Down
6 changes: 3 additions & 3 deletions mysql/index/2000w.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ select (@i:=@i+1) as rownum, person_name from person, (select @i:=100) as init;
set @i=1;
```

运行下面的 sql,连续执行 20 次,就是 2 的 20 次方约等于 100w 的数据;执行 23 次就是 2 的 23 次方约等于 800w , 如此下去即可实现千万测试数据的插入。
运行下面的 SQL,连续执行 20 次,就是 2 的 20 次方约等于 100w 的数据;执行 23 次就是 2 的 23 次方约等于 800w如此下去即可实现千万测试数据的插入。

如果不想翻倍翻倍的增加数据,而是想少量,少量的增加,有个技巧,就是在 SQL 的后面增加 where 条件,如 id > 某一个值去控制增加的数据量即可。

Expand Down Expand Up @@ -86,7 +86,7 @@ CREATE TABLE person(
) comment '人员信息表';
```

看看上面的建表 sql。id 是主键,本身就是唯一的,也就是说主键的大小可以限制表的上限:
看看上面的建表 SQL。id 是主键,本身就是唯一的,也就是说主键的大小可以限制表的上限:

- 如果主键声明 `int` 类型,也就是 32 位,那么支持 2^32-1 ~~21 亿;
- 如果主键声明 `bigint` 类型,那就是 2^62-1(36893488147419103232),难以想象这个的多大了,一般还没有到这个限制之前,可能数据库已经爆满了!!
Expand Down Expand Up @@ -224,7 +224,7 @@ CREATE TABLE person(

同样,还是按照 z = 3 的值来计算,那 Total = (1280 ^2) *3 = 4915200(近 500w)

所以,在保持相同的层级(相似查询性能)的情况下,在行数据大小不同的情况下,其实这个最大建议值也是不同的,而且影响查询性能的还有很多其他因素,比如,数据库版本,服务器配置,sql 的编写等等。
所以,在保持相同的层级(相似查询性能)的情况下,在行数据大小不同的情况下,其实这个最大建议值也是不同的,而且影响查询性能的还有很多其他因素,比如,数据库版本,服务器配置,SQL 的编写等等。

MySQL 为了提高性能,会将表的索引装载到内存中,在 InnoDB buffer size 足够的情况下,其能完成全加载进内存,查询不会有问题。

Expand Down
2 changes: 1 addition & 1 deletion mysql/index/index_interview.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

## 索引的分类

你知道索引有哪些吗?大家肯定都能霹雳啪啦地说出聚簇索引、主键索引、二级索引、普通索引、唯一索引、hash 索引、B+树索引等等。
你知道索引有哪些吗?大家肯定都能霹雳啪啦地说出聚簇索引、主键索引、二级索引、普通索引、唯一索引、Hash 索引、B+ 树索引等等。

然后再问你,你能将这些索引分一下类吗?可能大家就有点模糊了。其实,要对这些索引进行分类,要清楚这些索引的使用和实现方式,然后再针对有相同特点的索引归为一类。

Expand Down
2 changes: 1 addition & 1 deletion mysql/index/index_lose.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ InnoDB 存储引擎根据索引类型不同,分为聚簇索引(上图就是
select * from t_user where id=1;
```

在我们使用「二级索引」字段作为条件查询的时候,如果要查询的数据都在「聚簇索引」的叶子节点里,那么需要检索两颗 B+树:
在我们使用「二级索引」字段作为条件查询的时候,如果要查询的数据都在「聚簇索引」的叶子节点里,那么需要检索两颗 B+ 树:

- 先在「二级索引」的 B+ 树找到对应的叶子节点,获取主键值;
- 然后用上一步获取的主键值,在「聚簇索引」中的 B+ 树检索到对应的叶子节点,然后获取要查询的数据。
Expand Down
6 changes: 3 additions & 3 deletions mysql/index/why_index_chose_bpuls_tree.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ B 树进行单个索引查询时,最快可以在 O(1) 的时间代价内就查

但是 B 树的查询波动会比较大,因为每个节点既存索引又存记录,所以有时候访问到了非叶子节点就可以找到索引,而有时需要访问到叶子节点才能找到索引。

**B+ 树的非叶子节点不存放实际的记录数据,仅存放索引,因此数据量相同的情况下,相比既存索引又存记录的 B 树,B+树的非叶子节点可以存放更多的索引,因此 B+ 树可以比 B 树更「矮胖」,查询底层节点的磁盘 I/O 次数会更少**。
**B+ 树的非叶子节点不存放实际的记录数据,仅存放索引,因此数据量相同的情况下,相比既存索引又存记录的 B 树,B+ 树的非叶子节点可以存放更多的索引,因此 B+ 树可以比 B 树更「矮胖」,查询底层节点的磁盘 I/O 次数会更少**。

### 2、插入和删除效率

Expand Down Expand Up @@ -218,7 +218,7 @@ B 树和 B+ 树等值查询原理基本一致,先从根节点查找,然后

而 B 树没有将所有叶子节点用链表串联起来的结构,因此只能通过树的遍历来完成范围查询,这会涉及多个节点的磁盘 I/O 操作,范围查询效率不如 B+ 树。

因此,存在大量范围检索的场景,适合使用 B+树,比如数据库。而对于大量的单个索引查询的场景,可以考虑 B 树,比如 nosql 的 MongoDB。
因此,存在大量范围检索的场景,适合使用 B+ 树,比如数据库。而对于大量的单个索引查询的场景,可以考虑 B 树,比如 NoSQL 的 MongoDB。

### MySQL 中的 B+ 树

Expand Down Expand Up @@ -255,7 +255,7 @@ B 树和 B+ 都是通过多叉树的方式,会将树的高度变矮,所以

但是 MySQL 默认的存储引擎 InnoDB 采用的是 B+ 作为索引的数据结构,原因有:

- B+ 树的非叶子节点不存放实际的记录数据,仅存放索引,因此数据量相同的情况下,相比既存索引又存记录的 B 树,B+树的非叶子节点可以存放更多的索引,因此 B+ 树可以比 B 树更「矮胖」,查询底层节点的磁盘 I/O 次数会更少。
- B+ 树的非叶子节点不存放实际的记录数据,仅存放索引,因此数据量相同的情况下,相比既存索引又存记录的 B 树,B+ 树的非叶子节点可以存放更多的索引,因此 B+ 树可以比 B 树更「矮胖」,查询底层节点的磁盘 I/O 次数会更少。
- B+ 树有大量的冗余节点(所有非叶子节点都是冗余索引),这些冗余索引让 B+ 树在插入、删除的效率都更高,比如删除根节点的时候,不会像 B 树那样会发生复杂的树的变化;
- B+ 树叶子节点之间用链表连接了起来,有利于范围查询,而 B 树要实现范围查询,因此只能通过树的遍历来完成范围查询,这会涉及多个节点的磁盘 I/O 操作,范围查询效率不如 B+ 树。

Expand Down
2 changes: 1 addition & 1 deletion mysql/lock/how_to_lock.md
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ Empty set (0.00 sec)

我们先要清楚,什么情况下插入语句会发生阻塞。

**插入语句在插入一条记录之前,需要先定位到该记录在 B+树 的位置,如果插入的位置的下一条记录的索引上有间隙锁,才会发生阻塞**。
**插入语句在插入一条记录之前,需要先定位到该记录在 B+ 树 的位置,如果插入的位置的下一条记录的索引上有间隙锁,才会发生阻塞**。

在分析二级索引的间隙锁是否可以成功插入记录时,我们要先要知道二级索引树是如何存放记录的?

Expand Down
Loading
Loading