Update MySQL_基础.md

This commit is contained in:
heibaiying 2019-12-30 15:23:21 +08:00 committed by GitHub
parent 2ce7b78be6
commit beede5d95e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -31,13 +31,13 @@
### 1.1 InnoDB
InnoDB 是 MySQL 5.5 之后默认的存储引擎,它兼具高可靠和高性能的特性,主要具备以下优势:
InnoDB 是 MySQL 5.5 之后默认的存储引擎,它具有高可靠、高性能的特点,主要具备以下优势:
+ DML 操作完全遵循 ACID 模型,支持事务,支持崩溃恢复,能够极大地保护用户的数据安全;
+ 支持多版本并发控制,它会保存数据的旧版本信息,从而可以支持并发和事务的回滚;
+ 支持行级锁,支持类似 Oracle 的一致性读的特性,从而可以承受高并发地访问;
+ InnoDB 组织数据时默认按照主键进行聚簇从而可以提高主键查找的效率。对于频繁访问的数据InnoDB 还会为其建立哈希索引,从而提高等值查询的效率,这称为自适应哈希索引。
+ InnoDB 基于磁盘进行存储,所有存储记录按 **页** 的方式进行管理。为弥补 CPU 速度与磁盘速度之间的鸿沟InnoDB 引用缓存池 (Buffer Pool) 来提高数据的整体性能。查询时,会将目标页读缓存中;修改时,会先修改缓冲池中的页,然后再遵循 CheckPoint 机制将页刷回磁盘。所有缓存页通过最近最少使用原则 ( LRU ) 来进行定期清理。
+ InnoDB 组织数据时默认按照主键进行聚簇从而可以提高主键查找的效率。对于频繁访问的数据InnoDB 还会为其建立哈希索引,从而提高等值查询的效率,这也称为自适应哈希索引;
+ InnoDB 基于磁盘进行存储,所有存储记录按 **页** 的方式进行管理。为弥补 CPU 速度与磁盘速度之间的鸿沟InnoDB 引用缓存池 (Buffer Pool) 来提高数据的整体性能。查询时,会将目标页读缓存中;修改时,会先修改缓冲池中的页,然后再遵循 CheckPoint 机制将页刷回磁盘。所有缓存页通过最近最少使用原则 ( LRU ) 来进行定期清理。
+ InnoDB 支持两次写 (DoubleWrite) ,从而可以保证数据的安全,提高系统的可靠性。
一个 InnoDB 引擎完整的内存结构和磁盘结构如下图所示:
@ -53,7 +53,7 @@ MyISAM 是 MySQL 5.5 之前默认的存储引擎。创建 MyISAM 表时会创建
+ 扩展名为 `.MYD``MYData`):用于存储表数据;
+ 扩展名为 `.MYI` `MYIndex` 用于存储表的索引信息。
在 MySQL 8.0 之后,只会创建上述两个同名文件,因为在该版本中表结构的定义存储在 MySQL 数据字典中,但在 MySQL 8.0 之前,还会存在一个扩展名为 `.frm` 的文件用于存储表结构信息。MyISAM 与 InnoDB 主要的区别其只支持表级锁,不支持行级锁,不支持事务,不支持自动崩溃恢复,但可以使用内置的 mysqlcheck 和 myisamchk 工具来进行检查和修复。
在 MySQL 8.0 之后,只会创建上述两个同名文件,因为 8.0 后表结构的定义存储在 MySQL 数据字典中,但在 MySQL 8.0 之前,还会存在一个扩展名为 `.frm` 的文件用于存储表结构信息。MyISAM 与 InnoDB 主要的区别其只支持表级锁,不支持行级锁,不支持事务,不支持自动崩溃恢复,但可以使用内置的 mysqlcheck 和 myisamchk 工具来进行检查和修复。
### 1.3 MEMORY
@ -76,7 +76,7 @@ CSV 存储引擎使用逗号分隔值的格式将数据存储在文本文件中
### 1.5 ARCHIVE
ARCHIVE 默认采用 zlib 无损数据压缩算法进行数据压缩能够利用极小的空间存储大量的数据。创建ARCHIVE 表时,存储引擎会创建与表同名的 `ARZ` 文件,用于存储数据。它还具有以下特点:
ARCHIVE 存储引擎默认采用 zlib 无损数据压缩算法进行数据压缩能够利用极小的空间存储大量的数据。创建ARCHIVE 表时,存储引擎会创建与表同名的 `ARZ` 文件,用于存储数据。它还具有以下特点:
+ ARCHIVE 引擎支持 INSERTREPLACE 和 SELECT但不支持 DELETE 或 UPDATE。
+ ARCHIVE 引擎支持 AUTO_INCREMENT 属性,并支持在其对应的列上建立索引,如果尝试在不具有 AUTO_INCREMENT 属性的列上建立索引,则会抛出异常。
@ -84,7 +84,7 @@ ARCHIVE 默认采用 zlib 无损数据压缩算法进行数据压缩,能够
### 1.6 MEGRE
MERGE 存储引擎,也称为 MRG_MyISAM 引擎,是一组相同 MyISAM 表的集合。 ”相同” 表示所有表必须具有相同的列数据类型和索引信息。可以通过 UNION =list-of-tables选项来创建 MERGE 表,如下:
MERGE 存储引擎,也称为 MRG_MyISAM 引擎,是一组相同 MyISAM 表的集合。 ”相同” 表示所有表必须具有相同的列数据类型和索引信息。可以通过 `UNION = (list-of-tables)` 选项来创建 MERGE 表,如下:
```sql
mysql> CREATE TABLE t1 ( a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, message CHAR(20)) ENGINE=MyISAM;
@ -95,7 +95,7 @@ mysql> CREATE TABLE total (a INT NOT NULL AUTO_INCREMENT,message CHAR(20), INDEX
ENGINE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;
```
创建表时通过 INSERT_METHOD 选项来控制 MERGE 表的插入:使用 FIRST 或 LAST 分别表示在第一个或最后一个基础表中进行插入;如果未指定 INSERT_METHOD 或者设置值为 NO ,则表示不允许在 MERGE 表上执行插入操作。MERGE 表支持 SELECTDELETEUPDATE 和 DELETE 语句,示例如下:
创建表时可以通过 `INSERT_METHOD` 选项来控制 MERGE 表的插入:使用 `FIRST``LAST` 分别表示在第一个或最后一个基础表中进行插入;如果未指定 INSERT_METHOD 或者设置值为 NO ,则表示不允许在 MERGE 表上执行插入操作。MERGE 表支持 SELECTDELETEUPDATE 和 DELETE 语句,示例如下:
```sql
mysql> SELECT * FROM total;
@ -120,15 +120,19 @@ mysql> SELECT * FROM total;
**平衡二叉树数据结构**
<div align="center"> <img src="../pictures/avl-tree.png"/> </div>
**红黑树数据结构**
<div align="center"> <img src="../pictures/red-black-tree.png"/> </div>
**Btree 数据结构**
<div align="center"> <img src="../pictures/btree.png"/> </div>
**B+ Tree 数据结构**
<div align="center"> <img src="../pictures/B+Trees.png"/> </div>
> 以上图片均通过数据结构可视化网站 [Data Structure Visualizations](https://www.cs.usfca.edu/~galles/visualization/Algorithms.html) 自动生成,感兴趣的小伙伴也可自行尝试。
从上面的图示中我们可以看出 B+ Tree 树具有以下优点:
@ -136,7 +140,7 @@ mysql> SELECT * FROM total;
+ B+ Tree 树的所有非叶子节点 (如 003007),都会在叶子节点冗余一份,所有叶子节点都按照链表的方式进行组织,这样带来的好处是在范围查询中,只需要通过遍历叶子节点就可以获取到所有的索引信息。
+ B+ Tree 的所有非叶子节点都可以存储多个数据值,这取决于节点的大小,在 MySQL 中每个节点的大小为 16K ,因此其具备更大的出度,即在相同的数据量下,其树的高度更低。
+ 所有非叶子节点都只存储索引值,不存储实际的数据,只有叶子节点才会存储指针信息或数据信息。按照每个节点为 16K 的大小计算,对于千万级别的数据,其树的高度通常都在 3~6 左右 (取决于索引值的字节数),因此其查询性能非常优异。
+ 叶子节点存储的数据取决于不同数据库的实现,对于 MySQL 来说,取决于使用的存储引擎和是否是主键索引。
+ 叶子节点存储的数据取决于不同数据库的实现,对于 MySQL 来说,取决于使用的存储引擎和是否是主键索引。
### 2.2 B+ tree 索引
@ -146,12 +150,12 @@ mysql> SELECT * FROM total;
对于 MyISAM因为主键索引是非聚集索引所以其叶子节点存储的只是指向数据位置的指针
<div align="center"> <img src="../pictures/mysql-myisam-索引.png"/> </div>
综上所述B+ tree 普遍适用于范围查找优化排序和分组等操作。B+ tree 的查找是基于字典序的,因此其适用的具体查询类型如下
综上所述B+ tree 结构普遍适用于范围查找优化排序和分组等操作。B+ tree 是基于字典序进行构建的,因此其适用于以下查询
+ **全值匹配**:以索引为条件进行精确查找。如 `emp_no` 字段为索引,查询条件为 `emp_no = 10008`
+ **前缀匹配**:以联合索引的前缀为查找条件。如 `emp_no``dept_no` 为联合索引,查找条件为 `emp_no = 10008`
+ **全值匹配**:以索引为条件进行精确查找。如 `emp_no` 字段为索引,查询条件为 `emp_no = 10008`
+ **前缀匹配**:以联合索引的前缀为查找条件。如 `emp_no``dept_no` 为联合索引,查找条件为 `emp_no = 10008`
+ **列前缀匹配**:匹配索引列的值的开头部分。如 `dept_no` 为索引,查询条件为 `dept_no like "d1%"`。前缀匹配和列前缀匹配都是索引前缀性的体现,在某些时候也称为前缀索引。
+ **匹配范围值**:按照索引列匹配一定范围内的值。如 `emp_no` 字段为索引,查询条件为 `emp_no > 10008`
+ **匹配范围值**:按照索引列匹配一定范围内的值。如 `emp_no` 字段为索引,查询条件为 `emp_no > 10008`
+ **只访问索引的查询**:如 `emp_no` 字段为索引,查询语句为 `select emp_no from employees`,此时 emp_no 索引被称为本次查询的覆盖索引,即只需要从索引上就可以获取全部的查询信息,而不必访问实际的表中的数据。
+ **精确匹配某一列并范围匹配某一列**:如 `emp_no``dept_no` 为联合索引,查找条件为 `dept_no = "d004" and emp_no < 10020`,这种情况下索引顺序必须为 ( emp_nodept_no ),这样才能基于 emp_no 的字典序排序进行范围查找。
@ -171,7 +175,7 @@ InnoDB 引擎有一个名为 “自适应哈希索引 (adaptive hash index)”
- 在查询时,应该避免在索引列上使用函数或者表达式。
- 对于多列索引,应该按照使用频率由高到低的顺序建立联合索引。
- 尽量避免创建冗余的索引。如存在索引 (AB),接着又创建了索引 A索引 A 是索引 (AB) 的前缀索引,从而出现冗余。
- 尽量避免创建冗余的索引。如存在索引 (AB),接着又创建了索引 A因为索引 A 是索引 (AB) 的前缀索引,从而出现冗余。
- 建立索引时,应该考虑查询时候的排序和分组的需求。只有当索引列的顺序和 ORDER BY 字句的顺序完全一致并且遵循同样的升序或降序规则时候MySQL 才会使用索引来对结果做排序。
## 三、锁
@ -180,8 +184,8 @@ InnoDB 引擎有一个名为 “自适应哈希索引 (adaptive hash index)”
InnoDB 存储引擎支持以下两种标准的行级锁:
+ 共享锁 ( S Lock又称读锁):允许加锁事务读取数据;
+ 排它锁 ( X Lock又称写锁):允许加锁事务删除或者修改数据。
+ **共享锁 (S Lock又称读锁)** :允许加锁事务读取数据;
+ **排它锁 (X Lock又称写锁)** :允许加锁事务删除或者修改数据。
排它锁和共享锁的兼容情况如下:
@ -194,8 +198,8 @@ InnoDB 存储引擎支持以下两种标准的行级锁:
为了说明意向锁的作用,这里先引入一个案例:假设事务 A 利用 S 锁锁住了表中的某一行,让其只能读不能写。之后事务 B 尝试申请整个表的写锁,如果事务 B 申请成功,那么理论上它就应该能修改表中的任意一行,这与事务 A 持有的行锁是冲突的。想要解决这个问题,数据库必须知道表中某一行已经被锁定,从而在事务 B 尝试申请整个表的写锁时阻塞它。想要知道表中某一行被锁定,可以对表的每一行进行遍历,这种方式可行但是性能比较差,所以 InnoDB 引入了意向锁。
+ 意向共享锁 ( IS Lock ):当前表中某行或者某几行数据存在共享锁;
+ 意向排它锁 ( LX Lock ):当前表中某行或者某几行数据存在排它锁。
+ **意向共享锁 (IS Lock)** :当前表中某行或者某几行数据存在共享锁;
+ **意向排它锁 (LX Lock)** :当前表中某行或者某几行数据存在排它锁。
按照意向锁的规则,当上面的事务 A 给表中的某一行加 S 锁时,会同时给表加上 IS 锁,之后事务 B 尝试获取表的 X 锁时,由于 X 锁与 IS 锁并不兼容,所以事务 B 会被阻塞。
@ -266,7 +270,7 @@ InnoDB 存储引擎完全支持 ACID 模型:
**4. 持久性Durability**
一旦事务提交,则其所做的修改将会永远保存到数据库中。即使宕机等故障,也不丢失。
一旦事务提交,则其所做的修改将会永远保存到数据库中。即使宕机等故障,也不丢失。
### 4.2 事务的实现
@ -284,16 +288,19 @@ InnoDB 存储引擎完全支持 ACID 模型:
一个事务的更新操作被另外一个事务的更新操作锁覆盖,从而导致数据不一致:
<div align="center"> <img src="../pictures/mysql-修改丢失.png"/> </div>
**2. 脏读**
在不同的事务下,一个事务读取到其他事务未提交的数据:
<div align="center"> <img src="../pictures/mysql-脏读.png"/> </div>
**3. 不可重复读**
在同一个事务的两次读取之间,由于其他事务对数据进行了修改,导致对同一条数据两次读到的结果不一致:
<div align="center"> <img src="../pictures/mysql-不可重复读.png"/> </div>
**4.幻读**
在同一个事务的两次读取之间,由于其他事务对数据进行了修改,导致第二次读取到第一次不存在数据,或第一次原本存在的数据,第二次却读取不到,就好像之前的读取是 “幻觉” 一样: