mysql高级篇学习笔记
目录
- 前言
- 1 mysql安装及运行(linux环境)
- 2 数据目录
- 3 用户权限与管理
- 4 逻辑架构
- 5 存储引擎
- 6 索引的数据结构
- 7 InnoDB数据存储结构
- 8 索引的创建与设计原则
- 9 性能分析工具的使用
- 10 索引优化与查询优化
- 11 数据库的设计规范
- 12 数据库其它调优策略
- 13 事务基础知识
- 14 MySQL事务日志
- 15 锁
- 16 多版本控制
- 17 其他数据库日志
- 18 主从复制
- 19 数据库备份与恢复
- 20 MySQL常用命令
- 总结
前言
基于尚硅谷宋红康康师傅的mysql高级篇的学习。感谢康师傅。感谢尚硅谷。
1 mysql安装及运行(linux环境)
1.1 安装前检查
- 如果你是用rpm安装, 检查一下RPM PACKAGE:
rpm -qa | grep -i mysql # -i 忽略大小写
- 检查mysql service:
systemctl status mysqld.service
1.2 MySQL卸载
①关闭 mysql 服务
systemctl stop mysqld.service
②查看当前 mysql 安装状况
rpm -qa | grep -i mysql
#或
yum list installed | grep mysql
③卸载上述命令查询出的已安装程序
yum remove mysql-xxx mysql-xxx mysql-xxx mysqk-xxxx
务必卸载干净,反复执行 rpm -qa | grep -i mysql
确认是否有卸载残留
④删除 mysql 相关文件
- 查找相关文件
find / -name mysql
- 删除上述命令查找出的相关文件
rm -rf xxx
⑤删除 my.cnf
rm -rf /etc/my.cnf
1.3 安装
① 下载
② 安装、运行及登录
安装方式
安装方式 | 特点 |
---|---|
rpm | 安装简单,灵活性差,无法灵活选择版本、升级 |
rpm repository | 安装包极小,版本安装简单灵活,升级方便,需要联网安装 |
通用二进制包 | 安装比较复杂,灵活性高,平台通用性好 |
源码包 | 安装最复杂,时间长,参数设置灵活,性能好 |
注意:
rpm -ivh
i:install
v:提示
h:进度条
1.4 字符集问题
1.5 SQL书写规范(建议)
1.6 宽松模式和严格模式
2 数据目录
2.1 主要目录结构
2.2 查看默认数据库
2.3 数据库在文件系统中的表示
2.4 表在文件系统中的表示(InnoDB和MyISAM)
描述表结构:.frm文件
存储数据和索引(独立表空间):.ibd文件
2.5 小结
3 用户权限与管理
3.1 用户管理
3.1.1 登录
mysql数据库中有一个user表,表中存放的是用户。
3.1.2 创建用户
3.1.3 修改用户名
3.1.4 删除用户
3.1.5 设置当前用户密码
注意修改密码的时候host是localhost
还是%
。
3.1.6 修改其他用户密码
3.1.7 mysql8密码管理(了解)
3.2 权限
3.2.1 权限列表及授权权限原则
3.2.2 授予权限
3.2.3 查看权限
3.2.4 收回权限
3.3 权限表
3.3.1 user表
3.3.2 db表
3.3.3 tables_priv表和columns_priv表
3.3.4 procs_priv 表
3.4 访问控制(了解)
3.5 角色管理
3.5.1 理解
3.5.2 创建角色
3.5.3 给角色赋予权限
举例:
3.5.4 查看角色的权限
3.5.5 回收角色的权限
3.5.6 删除角色
3.5.7 给用户赋予角色
3.5.8 激活角色、撤销角色及设置强制角色
4 逻辑架构
4.1 逻辑架构剖析
4.1.2 三大层(连接层、服务层、引擎层)
4.1.3 存储层
4.1.4 小结
4.2 SQL执行流程
4.2.1 MySQL中的SQL执行流程
4.2.2 MySQL8.0执行原理
4.2.3 MySQL5.7执行原理
4.2.4 oracle中SQL执行流程
4.3 数据库缓冲池
4.3.1 缓冲池 vs 查询缓存
4.3.2 缓冲池如何读取数据及查看/设置大小
5 存储引擎
5.1 查看及设置默认存储引擎
5.2 设置表的存储引擎
5.3 引擎介绍
5.3.1 InnoDB 引擎:具备外键支持功能的事务存储引擎
5.3.2 MyISAM 引擎:主要的非事务处理存储引擎
5.3.3 Archive 引擎:用于数据存档
5.3.4 引擎对比
5.4 MyISAM和InnoDB
5.5 课外补充
6 索引的数据结构
6.1 使用索引的原因
6.2 索引优缺点
6.3 InnoDB中索引的推演
6.3.1 设计索引
[1] 一个简单的索引设计方案
[2] InnoDB中的索引方案(迭代3次)
[3] B+树
6.4 常见索引概念
6.4.1 聚簇索引
6.4.2 二级索引(辅助索引、非聚簇索引)
6.4.3 联合索引
6.5 注意事项
6.6 MyISAM中的索引方案
6.6.1 MyISAM 与 InnoDB对比
6.6 MySQL数据结构选择的合理性
6.6.1 Hash结构
6.6.2 二叉搜索树
6.6.3 AVL树
6.6.4 B-Tree
6.6.5 B+Tree
6.6.6 几道思考题
6.6.7 R树
7 InnoDB数据存储结构
7.1 数据页内部结构
7.1.1 文件头部
7.1.2 文件尾部
7.1.3 页目录
7.1.4 页面头部
7.2 InnoDB行格式(或记录格式)
7.2.1 指定行格式的语法
7.2.2 COMPACT行格式
7.2.3 Dynamic和Compressed行格式
[1] 行溢出
[2] Dynamic和Compressed行格式
7.2.4 Redundant行格式
8 索引的创建与设计原则
知识补充:
constraint
:表级约束,作用于一个列或者多个列。有四种可定义的约束:(主键、外键、唯一、检查)。
列级约束:作用于一个列,定义在列的后面,可以有多个约束,用空格隔开,有六种可定义的约束。
[constraint <外键约束名称>] foreign key(从表的某个字段) references 主表名(被参考字段)
#(从表的某个字段)的数据类型必须与主表名(被参考字段)的数据类型一致,逻辑意义也一样。
#(从表的某个字段)的字段名可以与主表名(被参考字段)的字段名一样,也可以不一样。
– foreign key :在表级指定子表中的列
– references :标示在父表中的列
- MySQL数据库中,unsigned表⾯含义是 '⽆符号’的意思,unsigned既为⾮负数,⽤此类型可以增加数据长度。
8.1 索引的声明与使用
8.1.1 索引的分类
8.1.2 创建索引
[1] 创建表的时候创建索引
[2] 在已经存在的表上创建索引
[3] 删除索引
8.2 MySQL 8.0索引新特性
8.2.1 支持降序索引
8.2.2 隐藏索引
8.3 索引的设计原则
8.3.1 准备数据
8.3.2 哪些情况适合创建索引
8.3.3 哪些情况不适合创建索引
9 性能分析工具的使用
9.1 数据库服务器的优化步骤
9.2 查看系统性能参数
9.3 统计SQL的查询成本:last_query_cost
9.4 定位执行慢的sql:慢查询日志
9.4.1 开启慢查询日志参数
9.4.2 查看慢查询数目及案例演示
9.4.3 慢查询日志分析工具:mysqldumpslow
9.5 分析查询工具:EXPLAIN
9.5.1 概述及基本语法
9.5.2 数据准备
9.5.3 EXPLAIN各列作用
[1] tabel + id
[2] select_type(重点)
[3] partitions(可略) + type(重点)
[4] possible_keys + key +ref
[5] rows(重点)+ filtered
[6] Extra
[7] 小结
#1. table:表名
#查询的每一行记录都对应着一个单表
EXPLAIN SELECT * FROM s1;
#s1:驱动表 s2:被驱动表
EXPLAIN SELECT * FROM s1 INNER JOIN s2;
#2. id:在一个大的查询语句中每个SELECT关键字都对应一个唯一的id
SELECT * FROM s1 WHERE key1 = 'a';
SELECT * FROM s1 INNER JOIN s2
ON s1.key1 = s2.key1
WHERE s1.common_field = 'a';
SELECT * FROM s1
WHERE key1 IN (SELECT key3 FROM s2);
SELECT * FROM s1 UNION SELECT * FROM s2;
EXPLAIN SELECT * FROM s1 WHERE key1 = 'a';
EXPLAIN SELECT * FROM s1 INNER JOIN s2;
EXPLAIN SELECT * FROM s1 WHERE key1 IN (SELECT key1 FROM s2) OR key3 = 'a';
######查询优化器可能对涉及子查询的查询语句进行重写,转变为多表查询的操作########
EXPLAIN SELECT * FROM s1 WHERE key1 IN (SELECT key2 FROM s2 WHERE common_field = 'a');
#Union去重
EXPLAIN SELECT * FROM s1 UNION SELECT * FROM s2;
EXPLAIN SELECT * FROM s1 UNION ALL SELECT * FROM s2;
#3. select_type:SELECT关键字对应的那个查询的类型,确定小查询在整个大查询中扮演了一个什么角色
# 查询语句中不包含`UNION`或者子查询的查询都算作是`SIMPLE`类型
EXPLAIN SELECT * FROM s1;
#连接查询也算是`SIMPLE`类型
EXPLAIN SELECT * FROM s1 INNER JOIN s2;
#对于包含`UNION`或者`UNION ALL`或者子查询的大查询来说,它是由几个小查询组成的,其中最左边的那个
#查询的`select_type`值就是`PRIMARY`
#对于包含`UNION`或者`UNION ALL`的大查询来说,它是由几个小查询组成的,其中除了最左边的那个小查询
#以外,其余的小查询的`select_type`值就是`UNION`
#`MySQL`选择使用临时表来完成`UNION`查询的去重工作,针对该临时表的查询的`select_type`就是
#`UNION RESULT`
EXPLAIN SELECT * FROM s1 UNION SELECT * FROM s2;
EXPLAIN SELECT * FROM s1 UNION ALL SELECT * FROM s2;
#子查询:
#如果包含子查询的查询语句不能够转为对应的`semi-join`的形式,并且该子查询是不相关子查询。
#该子查询的第一个`SELECT`关键字代表的那个查询的`select_type`就是`SUBQUERY`
EXPLAIN SELECT * FROM s1 WHERE key1 IN (SELECT key1 FROM s2) OR key3 = 'a';
#如果包含子查询的查询语句不能够转为对应的`semi-join`的形式,并且该子查询是相关子查询,
#则该子查询的第一个`SELECT`关键字代表的那个查询的`select_type`就是`DEPENDENT SUBQUERY`
EXPLAIN SELECT * FROM s1
WHERE key1 IN (SELECT key1 FROM s2 WHERE s1.key2 = s2.key2) OR key3 = 'a';
#注意的是,select_type为`DEPENDENT SUBQUERY`的查询可能会被执行多次。
#在包含`UNION`或者`UNION ALL`的大查询中,如果各个小查询都依赖于外层查询的话,那除了
#最左边的那个小查询之外,其余的小查询的`select_type`的值就是`DEPENDENT UNION`。
EXPLAIN SELECT * FROM s1
WHERE key1 IN (SELECT key1 FROM s2 WHERE key1 = 'a' UNION SELECT key1 FROM s1 WHERE key1 = 'b');
#对于包含`派生表`的查询,该派生表对应的子查询的`select_type`就是`DERIVED`
EXPLAIN SELECT *
FROM (SELECT key1, COUNT(*) AS c FROM s1 GROUP BY key1) AS derived_s1 WHERE c > 1;
#当查询优化器在执行包含子查询的语句时,选择将子查询物化之后与外层查询进行连接查询时,
#该子查询对应的`select_type`属性就是`MATERIALIZED`
EXPLAIN SELECT * FROM s1 WHERE key1 IN (SELECT key1 FROM s2); #子查询被转为了物化表
# 4. partition(略):匹配的分区信息
# 5. type:针对单表的访问方法
#当表中`只有一条记录`并且该表使用的存储引擎的统计数据是精确的,比如MyISAM、Memory,
#那么对该表的访问方法就是`system`。
CREATE TABLE t(i INT) ENGINE=MYISAM;
INSERT INTO t VALUES(1);
EXPLAIN SELECT * FROM t;
#换成InnoDB
CREATE TABLE tt(i INT) ENGINE=INNODB;
INSERT INTO tt VALUES(1);
EXPLAIN SELECT * FROM tt;
#当我们根据主键或者唯一二级索引列与常数进行等值匹配时,对单表的访问方法就是`const`
EXPLAIN SELECT * FROM s1 WHERE id = 10005;
EXPLAIN SELECT * FROM s1 WHERE key2 = 10066;
#在连接查询时,如果被驱动表是通过主键或者唯一二级索引列等值匹配的方式进行访问的
#(如果该主键或者唯一二级索引是联合索引的话,所有的索引列都必须进行等值比较),则
#对该被驱动表的访问方法就是`eq_ref`
EXPLAIN SELECT * FROM s1 INNER JOIN s2 ON s1.id = s2.id;
#当通过普通的二级索引列与常量进行等值匹配时来查询某个表,那么对该表的访问方法就可能是`ref`
EXPLAIN SELECT * FROM s1 WHERE key1 = 'a';
#当对普通二级索引进行等值匹配查询,该索引列的值也可以是`NULL`值时,那么对该表的访问方法
#就可能是`ref_or_null`
EXPLAIN SELECT * FROM s1 WHERE key1 = 'a' OR key1 IS NULL;
#单表访问方法时在某些场景下可以使用`Intersection`、`Union`、
#`Sort-Union`这三种索引合并的方式来执行查询
EXPLAIN SELECT * FROM s1 WHERE key1 = 'a' OR key3 = 'a';
#`unique_subquery`是针对在一些包含`IN`子查询的查询语句中,如果查询优化器决定将`IN`子查询
#转换为`EXISTS`子查询,而且子查询可以使用到主键进行等值匹配的话,那么该子查询执行计划的`type`
#列的值就是`unique_subquery`
EXPLAIN SELECT * FROM s1
WHERE key2 IN (SELECT id FROM s2 WHERE s1.key1 = s2.key1) OR key3 = 'a';
#如果使用索引获取某些`范围区间`的记录,那么就可能使用到`range`访问方法
EXPLAIN SELECT * FROM s1 WHERE key1 IN ('a', 'b', 'c');
#同上
EXPLAIN SELECT * FROM s1 WHERE key1 > 'a' AND key1 < 'b';
#当我们可以使用索引覆盖,但需要扫描全部的索引记录时,该表的访问方法就是`index`
EXPLAIN SELECT key_part2 FROM s1 WHERE key_part3 = 'a';
#最熟悉的全表扫描
EXPLAIN SELECT * FROM s1;
#6. possible_keys和key:可能用到的索引 和 实际上使用的索引
EXPLAIN SELECT * FROM s1 WHERE key1 > 'z' AND key3 = 'a';
#7. key_len:实际使用到的索引长度(即:字节数)
# 帮你检查`是否充分的利用上了索引`,`值越大越好`,主要针对于联合索引,有一定的参考意义。
EXPLAIN SELECT * FROM s1 WHERE id = 10005;
EXPLAIN SELECT * FROM s1 WHERE key2 = 10126;
EXPLAIN SELECT * FROM s1 WHERE key1 = 'a';
EXPLAIN SELECT * FROM s1 WHERE key_part1 = 'a';
EXPLAIN SELECT * FROM s1 WHERE key_part1 = 'a' AND key_part2 = 'b';
EXPLAIN SELECT * FROM s1 WHERE key_part1 = 'a' AND key_part2 = 'b' AND key_part3 = 'c';
EXPLAIN SELECT * FROM s1 WHERE key_part3 = 'a';
#练习:
#varchar(10)变长字段且允许NULL = 10 * ( character set:utf8=3,gbk=2,latin1=1)+1(NULL)+2(变长字段)
#varchar(10)变长字段且不允许NULL = 10 * ( character set:utf8=3,gbk=2,latin1=1)+2(变长字段)
#char(10)固定字段且允许NULL = 10 * ( character set:utf8=3,gbk=2,latin1=1)+1(NULL)
#char(10)固定字段且不允许NULL = 10 * ( character set:utf8=3,gbk=2,latin1=1)
# 8. ref:当使用索引列等值查询时,与索引列进行等值匹配的对象信息。
#比如只是一个常数或者是某个列。
EXPLAIN SELECT * FROM s1 WHERE key1 = 'a';
EXPLAIN SELECT * FROM s1 INNER JOIN s2 ON s1.id = s2.id;
EXPLAIN SELECT * FROM s1 INNER JOIN s2 ON s2.key1 = UPPER(s1.key1);
# 9. rows:预估的需要读取的记录条数
# `值越小越好`
EXPLAIN SELECT * FROM s1 WHERE key1 > 'z';
# 10. filtered: 某个表经过搜索条件过滤后剩余记录条数的百分比
#如果使用的是索引执行的单表扫描,那么计算时需要估计出满足除使用
#到对应索引的搜索条件外的其他搜索条件的记录有多少条。
EXPLAIN SELECT * FROM s1 WHERE key1 > 'z' AND common_field = 'a';
#对于单表查询来说,这个filtered列的值没什么意义,我们`更关注在连接查询
#中驱动表对应的执行计划记录的filtered值`,它决定了被驱动表要执行的次数(即:rows * filtered)
EXPLAIN SELECT * FROM s1 INNER JOIN s2 ON s1.key1 = s2.key1 WHERE s1.common_field = 'a';
#11. Extra:一些额外的信息
#更准确的理解MySQL到底将如何执行给定的查询语句
#当查询语句的没有`FROM`子句时将会提示该额外信息
EXPLAIN SELECT 1;
#查询语句的`WHERE`子句永远为`FALSE`时将会提示该额外信息
EXPLAIN SELECT * FROM s1 WHERE 1 != 1;
#当我们使用全表扫描来执行对某个表的查询,并且该语句的`WHERE`
#子句中有针对该表的搜索条件时,在`Extra`列中会提示上述额外信息。
EXPLAIN SELECT * FROM s1 WHERE common_field = 'a';
#当使用索引访问来执行对某个表的查询,并且该语句的`WHERE`子句中
#有除了该索引包含的列之外的其他搜索条件时,在`Extra`列中也会提示上述额外信息。
EXPLAIN SELECT * FROM s1 WHERE key1 = 'a' AND common_field = 'a';
#当查询列表处有`MIN`或者`MAX`聚合函数,但是并没有符合`WHERE`子句中
#的搜索条件的记录时,将会提示该额外信息
EXPLAIN SELECT MIN(key1) FROM s1 WHERE key1 = 'abcdefg';
EXPLAIN SELECT MIN(key1) FROM s1 WHERE key1 = 'NlPros'; #NlPros 是 s1表中key1字段真实存在的数据
#select * from s1 limit 10;
#当我们的查询列表以及搜索条件中只包含属于某个索引的列,也就是在可以
#使用覆盖索引的情况下,在`Extra`列将会提示该额外信息。比方说下边这个查询中只
#需要用到`idx_key1`而不需要回表操作:
EXPLAIN SELECT key1,id FROM s1 WHERE key1 = 'a';
#有些搜索条件中虽然出现了索引列,但却不能使用到索引
#看课件理解索引条件下推
EXPLAIN SELECT * FROM s1 WHERE key1 > 'z' AND key1 LIKE '%a';
#在连接查询执行过程中,当被驱动表不能有效的利用索引加快访问速度,MySQL一般会为
#其分配一块名叫`join buffer`的内存块来加快查询速度,也就是我们所讲的`基于块的嵌套循环算法`
#见课件说明
EXPLAIN SELECT * FROM s1 INNER JOIN s2 ON s1.common_field = s2.common_field;
#当我们使用左(外)连接时,如果`WHERE`子句中包含要求被驱动表的某个列等于`NULL`值的搜索条件,
#而且那个列又是不允许存储`NULL`值的,那么在该表的执行计划的Extra列就会提示`Not exists`额外信息
EXPLAIN SELECT * FROM s1 LEFT JOIN s2 ON s1.key1 = s2.key1 WHERE s2.id IS NULL;
#如果执行计划的`Extra`列出现了`Using intersect(...)`提示,说明准备使用`Intersect`索引
#合并的方式执行查询,括号中的`...`表示需要进行索引合并的索引名称;
#如果出现了`Using union(...)`提示,说明准备使用`Union`索引合并的方式执行查询;
#出现了`Using sort_union(...)`提示,说明准备使用`Sort-Union`索引合并的方式执行查询。
EXPLAIN SELECT * FROM s1 WHERE key1 = 'a' OR key3 = 'a';
#当我们的`LIMIT`子句的参数为`0`时,表示压根儿不打算从表中读出任何记录,将会提示该额外信息
EXPLAIN SELECT * FROM s1 LIMIT 0;
#有一些情况下对结果集中的记录进行排序是可以使用到索引的。
#比如:
EXPLAIN SELECT * FROM s1 ORDER BY key1 LIMIT 10;
#很多情况下排序操作无法使用到索引,只能在内存中(记录较少的时候)或者磁盘中(记录较多的时候)
#进行排序,MySQL把这种在内存中或者磁盘上进行排序的方式统称为文件排序(英文名:`filesort`)。
#如果某个查询需要使用文件排序的方式执行查询,就会在执行计划的`Extra`列中显示`Using filesort`提示
EXPLAIN SELECT * FROM s1 ORDER BY common_field LIMIT 10;
#在许多查询的执行过程中,MySQL可能会借助临时表来完成一些功能,比如去重、排序之类的,比如我们
#在执行许多包含`DISTINCT`、`GROUP BY`、`UNION`等子句的查询过程中,如果不能有效利用索引来完成
#查询,MySQL很有可能寻求通过建立内部的临时表来执行查询。如果查询中使用到了内部的临时表,在执行
#计划的`Extra`列将会显示`Using temporary`提示
EXPLAIN SELECT DISTINCT common_field FROM s1;
#EXPLAIN SELECT DISTINCT key1 FROM s1;
#同上。
EXPLAIN SELECT common_field, COUNT(*) AS amount FROM s1 GROUP BY common_field;
#执行计划中出现`Using temporary`并不是一个好的征兆,因为建立与维护临时表要付出很大成本的,所以
#我们`最好能使用索引来替代掉使用临时表`。比如:扫描指定的索引idx_key1即可
EXPLAIN SELECT key1, COUNT(*) AS amount FROM s1 GROUP BY key1;
#json格式的explain
EXPLAIN FORMAT=JSON SELECT * FROM s1 INNER JOIN s2 ON s1.key1 = s2.key2
WHERE s1.common_field = 'a';
以上是Mysql中代码示例,包含所有情况。
9.5.4 EXPALIN的进一步使用
[1]四种输出格式:传统格式、JSON格式、TREE格式、可视化输出
9.6 分析优化器执行计划:trace
9.7 MySQL监控分析视图-sys schema
10 索引优化与查询优化
10.1 数据准备
10.2 索引失效案例
[1] 全值匹配
[2] 最佳左前缀法则
[3] 主键插入顺序
[4] 计算、函数、类型转换(自动或者手动)导致索引失效
[5] 类型转换导致索引失效
[6] 范围条件右边的列索引失效
[7] 不等于(!= 或者<>)索引失效
[8] is null可以使用索引,is not null无法使用索引
[9] like以通配符%开头索引失效
[10] OR 前后存在非索引的列,索引失效
[11] 数据库和表的字符集统一使用utf8mb4
[12] 练习及一般性建议
10.3 关联查询优化
10.3.1 数据准备
10.3.2 采用左外连接
10.3.3 采用内连接
10.3.4 join语句原理
[1] 被驱动表和驱动表
[2] Simple Nested-Loop Join (简单嵌套循环连接)
[3] Index Nested-Loop Join (索引嵌套循环连接)
[4] Block Nested-Loop Join(块嵌套循环连接)
[5] join 小结
10.3.5 小结
10.4 子查询优化
10.5 排序优化
10.5.1 排序优化及测试
10.5.2 小结
10.5.3 案例实战
[1] 尽量让where的过滤条件和排序使用上索引
10.5.4 filesort算法:双路排序和单路排序
10.6 GROUP BY 优化
10.7 优化分页查询
10.8 优先考虑覆盖索引
10.8.1 什么是覆盖索引?
10.8.2 覆盖索引的利弊
10.9 如何给字符串添加索引
10.9.1 前缀索引
10.9.2 前缀索引对覆盖索引的影响
10.10 索引下推
10.10.1 使用前后对比
10.10.2 icp的开启/关闭
10.10.3 ICP使用案例
10.10.4 开启和关闭ICP性能对比
10.10.5 ICP的使用条件
10.11 普通索引 VS 唯一索引
10.11.1 查询过程及更新过程
10.11.2 change buffer 的使用场景
10.12 其他查询优化策略
10.12.1 EXISTS和IN的区分
10.12.2 count(*)与count(具体字段)效率
10.12.3 关于SELECT(*)
10.12.4 LIMIT 1 对优化的影响
10.12.5 多使用COMMIT
10.13 淘宝数据库的主键是如何设计的?
10.13.1 自增ID的问题
10.13.2 业务字段做主键
10.13.3 淘宝的主键设计
10.13.4 推荐的主键设计
11 数据库的设计规范
11.1 为什么需要数据库设计
11.2 范氏
11.2.1 范式简介
11.2.2 键和相关属性的概念
11.2.3 第一范式
11.2.4 第二范式
理解
11.2.5 第三范式
11.2.6 小结
11.3 反范式化
11.3.1 概述
11.3.2 应用举例
11.3.2 反范式的一些问题及适用场景
11.4 巴斯范式
11.5 第四范式
11.6 第五范式、域键范式
11.7 实战案例
11.7.1 迭代1-3次
11.7.2 反范式化:业务优先的原则
11.8 ER模型
11.8.1 ER模型包括哪些要素?
11.8.2 关系的类型
11.8.3 建模分析
11.8.4 ER模型的细化
11.8.5 ER模型图转换成数据表
[1] 一个实体转换成一个数据库
[2] 一个多对多的关系转换成一个数据表
[3] 通过外键来表达1对多的关系
[4] 把属性转换成表的字段
11.9 数据表的设计原则
11.10 数据库对象编写建议
11.10.1 关于库
11.10.2 关于表、列
11.10.3 关于索引
11.10.4 SQL编写
11.11 PowerDesigner的使用
11.11.1 开始界面
11.11.2 概念数据模型
11.11.3 物理数据模型
11.11.4 概念模型转换为物理模型
11.11.5 物理模型转换为概念模型
11.11.6 物理模型导出SQL语句
12 数据库其它调优策略
12.1 数据库调优的措施
12.1.1 调优的目标及如何定位调优问题
12.1.2 调优的维度和步骤
[1] 选择合适的DBMS和优化表设计
[2] 优化逻辑查询和优化物理查询
[3] 使用Redis或Memecached作为缓存
[4] 库级优化
12.2 优化MySQL服务器
12.2.1 优化服务器硬件及优化MySQL的参数
12.2.2 优化数据库结构
[1] 拆分表:冷热数据分离
[2] 增加中间表
[3] 增加冗余字段
[4] 优化数据类型
[5] 优化插入记录的速度
[6] 使用非空约束
[7] 分析表、检查表与优化表
12.3 大表优化
[1] 限定查询的范围
[2] 读\写分离
[3] 垂直拆分
[4] 水平拆分
12.4 其他调优策略
[1] 服务器语句超时处理
[2] 创建全局通用表空间
[3] MySQL8.0新特性:隐藏索引对调优的帮助
13 事务基础知识
13.1 数据库事务概述
13.1.1 存储引擎支持情况及基本概念
13.1.2 事务的ACID特性
13.1.3 事务的状态
13.2 如何使用事务
13.2.1 显式事务
13.2.2 隐式事务
13.2.3 隐式提交数据的情况
13.2.4 使用举例1:提交与回滚
13.2.5 使用举例2:测试不支持事务的engine
13.2.6 使用举例3:SAVEPOINT
13.3 事务隔离级别
13.3.1 数据并发问题
脏读:当前事务读取了另一个事务未提交写的记录。
不可重复读:当前事务事先读取了一条记录,另一事务又对这条记录进行了修改并提交,当前事务再次读取的时候,值不同。
幻读:当前事务读取了一个范围内的记录,另一事务又对该范围内的事务进行了添加新纪录。当当前事务再次读取的时候读取到了插入的新纪录。
13.3.2 SQL中的四种隔离级别
13.3.3 MySQL支持的四种隔离级别
13.3.4 如何设置事务的隔离级别
13.3.5 不同隔离级别举例
13.4 事务的常见分类
14 MySQL事务日志
14.1 redo日志
14.1.1 为什么需要REDO日志
14.1.2 REDO日志的好处、特点
14.1.3 redo的组成
14.1.4 redo的整体流程
14.1.5 redo log的刷盘策略
14.1.6 不同刷盘策略演示
[1] 流程图
[2] 举例
14.1.7 写入redo log buffer 过程
[1] 补充概念:Mini- Transaction
[2] redo 日志写入log buffer
[3] redo log block 的结构图
14.1.8 redo log file
[1] 相关参数设置
[2] 日志文件组
[3] checkpoint
14.1.9 redo log 小结
14.2 undo日志
14.2.1 如何理解undo日志
14.2.2 undo日志的作用
14.2.3 undo的存储结构
[1] 回滚段与undo页
[2] 回滚段与事务
[3] 回滚段中的数据分类
14.2.4 undo的类型
14.2.5 undo log的生命周期
[1] 简要生成过程
14.2.6 详细生成过程
[2] 详细生成过程
[3] undo log是如何回滚的
[4] undo log的删除
14.2.6 小结
15 锁
15.1 概述
15.2 MySQL并发事务访问相同记录
15.2.1 读-读情况
15.2.2 读-写情况
15.2.3 读-写或写-读情况
15.2.4 并发问题的解决方案
15.3 锁的不同角度分类
15.3.1 从数据操作的类型划分:读锁、写锁
15.3.2 从数据操作的粒度划分:表级锁、页级锁、行锁
[1] 表锁
① 表级别的s锁、x锁
② 意向锁
意向共享锁(Intention Shared Lock),简称 IS 锁。当事务准备在某条记录上加 S 锁时,需要先在表级别加一个 IS 锁。
意向独占锁(Intention Exclusive Lock),简称 IX 锁。当事务准备在某条记录上加 X 锁时,需要先在表级别加一个 IX 锁。
意向锁是表级锁,它们的提出仅仅为了在之后加表级别的 S 锁和 X 锁时可以快速判断表中的记录是否被上锁,以避免用遍历的方式来查看表中有没有上锁的记录。就是说其实 IS 锁和 IS 锁是兼容的,IX 锁和 IX 锁是兼容的。
为什么需要意向锁?
InnoDB 的意向锁主要用户多粒度的锁并存的情况。比如事务A要在一个表上加S锁,如果表中的一行已被事务 B 加了 X 锁,那么该锁的申请也应被阻塞。如果表中的数据很多,逐行检查锁标志的开销将很大,系统的性能将会受到影响。
举个例子,如果表中记录 1 亿,事务 A 把其中有几条记录上了行锁了,这时事务 B 需要给这个表加表级锁,如果没有意向锁的话,那就要去表中查找这一亿条记录是否上锁了。如果存在意向锁,那么假如事务A在更新一条记录之前,先加意向锁,再加X锁,事务 B 先检查该表上是否存在意向锁,存在的意向锁是否与自己准备加的锁冲突,如果有冲突,则等待直到事务A释放,而无须逐条记录去检测。事务B更新表时,其实无须知道到底哪一行被锁了,它只要知道反正有一行被锁了就行了。
说白了意向锁的主要作用是处理行锁和表锁之间的矛盾,能够显示某个事务正在某一行上持有了锁,或者准备去持有锁。
③ 自增锁
④ 元数据锁(MDL锁)
[2] InnoDB中的行锁
① 记录锁
② 间隙锁
③ 临键锁
④ 插入意向锁
15.3.3 从对待锁的态度划分:乐观锁、悲观锁
[1] 悲观锁
[2] 乐观锁
[3] 两种锁的适用场景
15.3.4 按加锁的方式划分:显式锁、隐式锁
[1] 隐式锁
[2] 显式锁
15.3.5 其他锁之:全局锁
15.3.6 其他锁之:死锁
15.4 锁的内存结构
15.5 锁监控
16 多版本控制
16.1 什么是mvcc
16.2 快照读与当前读
16.2.1 快照读
16.2.2 当前读
16.3 复习
16.3.1 隔离级别
16.3.2 隐藏字段、undo log版本链
16.4 mvcc实现原理之ReadView
16.4.1 什么是ReadView
16.4.2 设计思路
16.4.3 ReadView的规则
16.4.4 MVCC整体操作流程
16.5 举例说明
16.5.1 READ COMMITTED隔离级别下
16.5.2 REPEATABLE READ隔离级别下
16.5.3 如何解决幻读
16.6 总结
17 其他数据库日志
17.1 MySQL支持的日志
17.1.1 日志类型
17.1.2 日志的弊端
17.2 慢查询日志
17.3 通用查询日志
17.3.1 问题场景
17.3.2 查看当前状态
17.3.3 启动日志
17.3.4 查看日志
17.3.5 停止日志
17.3.6 删除/刷新日志
17.4 错误日志
17.4.1 启动日志
17.4.2 查看日志
17.4.3 删除/刷新日志
17.5 二进制日志(bin log)
17.5.1 查看默认情况
17.5.2 日志参数设置
17.5.3 查看日志
17.5.4 使用日志恢复数据
17.5.5 删除二进制日志
17.5.6 其他场景
17.6 再谈二进制日志(binlog)
17.6.1 写入机制
17.6.2 binlog 与 redolog对比
17.6.3 两阶段提交
17.7 中继日志(relay log)
17.7.1 介绍
17.7.2 查看中继日志
17.7.3 恢复的典型错误
18 主从复制
18.1 主从复制概述
18.1.1 如何提升数据库并发能力
18.1.2 主从复制的作用
18.2 主从复制的原理
18.2.1 原理剖析
18.2.2 复制的基本原则
18.3 一主一从架构搭建
18.3.1 准备工作
18.3.2 主机配置文件
[1] binlog格式设置
[2] ROW模式(基于行的复制(row-based repication,RBP))
[3] MIXED模式(混合模式复制(mixed-based replication, MBR))
18.3.3 从机配置文件
18.3.4 主机:建立账户并授权
18.3.5 从机:配置需要复制的主机
[1] 步骤1
[2] 步骤2
18.3.6 测试
18.3.7 停止主从同步
18.3.8 后续
搭建主从复制:双主双从
18.4 同步数据一致性问题
18.4.1 理解主从延迟问题
18.4.2 主从延迟问题原因
18.4.3 如何减少主从延迟
18.4.4 如何解决一致性问题
[1] 异步复制
[2] 半同步复制
[3] 组复制
18.5 知识延伸
19 数据库备份与恢复
19.1 物理备份与逻辑备份
19.2 mysqldump实现逻辑备份
19.2.1 备份一个数据库
19.2.2 备份全部数据库
19.2.3 备份部分数据库
19.2.4 备份部分表
19.2.5 备份单表的部分数据
19.2.6 排除某些表的备份
19.2.7 只备份结构或只备份数据
19.2.8 备份中包含存储过程、函数、事件
19.2.9 mysqldump常用选项
19.3 mysql命令恢复数据
19.3.1 单库备份中恢复单库
19.3.2 全量备份恢复
19.3.3. 从全量备份中恢复单库
表结构
表数据
19.3.4 从单库备份中恢复单表
19.4 物理备份:直接复制整个数据库
19.5 物理恢复:直接复制到数据库目录
19.6 表的导出与导入
19.6.1 表的导出
[1] 使用SELECT …INTO OUTFILE导出文本文件
[2] 使用mysqldump命令导出文本文件
[3] 使用mysql命令导出文本文件
19.6.2 表的导入
[1] 使用LOAD DATA INFILE方式导入文本文件
[2] 使用mysqlimport方式导入文本文件
19.7 数据库迁移
19.7.1 概述
19.7.2 迁移方案
19.7.3 迁移注意点
19.7.4 迁移小结
19.8 删除了不敢跑,能干点啥?
19.8.1 delete: 误删行
19.8.2 truncate/drop :误删库/表
19.8.3 延迟复制备库
19.8.4 预防误删库/表的方法
19.8.5 rm: 误删MySQL实例
20 MySQL常用命令
20.1 mysql
20.1.1 连接选项
20.1.2 执行选项
20.2 mysqladmin
20.3 mysqlbinlog
20.4 mysqldump
20.4.1 连接选项
20.4.2 输出内容选项
20.5 mysqlimport/source
20.6 mysqlshow
总结
让我们感谢尚硅谷康师傅的付出,为无数java学习和mysql学习中的学子提供了一个很好的课程资源。在本篇的学习中,还是有一部分知识不是太懂,希望在开发中能实操并真正理解吧。