MYSQL
SQL执行原理
连接器->查询缓存->解析器->优化器->执行器
8.0查询缓存去除了 在高并发和数据变化频繁(复杂查询类似带时间戳的)的现代应用场景中,查询缓存的性能逐渐消失,甚至可能成为性能瓶颈,不如直接在应用层做缓存,减轻数据压力。
SQL执行顺序
From:确定表
Join:链接表开始组合数据
where:初步筛选过滤行
group by:对数据进行分组
Having:对分组后的数据进行过滤
Select:查询
Distinct:去重
Order By:排序
Limit:限制返回行数
经典例子
where中使用select的别名会报错 group by可以使用是因为优化器的原因
索引
结构
b+tree
索引分类
聚簇索引 :叶子节点存放整行数据
非聚簇索引:叶子节点存放的是索引列和对应的主键
回表查询
查询的列没有在索引列中,查询没有完整查询到,需要去聚簇索引上查找剩余的列。
覆盖索引
查询的列都在索引中全覆盖 无需要回表查询。
索引下推
举一个例子:一个查询语句 select * from user where name ='"张三" and age ="64"
之前的查询过程是:引擎层只对第一个条件进行过滤,判断是否回表后,然后将其它的过滤添加交给server层。
有了索引下推后是:引擎层先过滤name在过滤age 然后在判断是否回表。
过滤条件尽可能的下推在引擎层执行,减少无用的回表查询 称为索引下推
索引失效
- 左百分号:因为索引树的特性,叶子节点是双向链表 ,有序的,百分号会导致索引不可用,全表扫描。
- 最左前缀:使用了联合索引,必须从最左的字段进行匹配
- 对列进行运算或函数:例如year(birthday) ,索引中找不到哪一段是2020 只能每个值进行year()
- select *:不走索引
- 使用or:分开查找然后合并 某些字段如果没有索引 优化器会选择全表扫描
- order by:排序字段顺序与索引不一致时,无法使用索引顺序
- not in和not exists:排除逻辑
- 字段类型不同
索引优化ExPlain
锁
表级锁
表锁
- 表共享读锁(Read Lock,读锁)
- 表独占写锁(Write Lock,写锁)
有写锁就会堵塞
元数据锁
防止DML和DDL语句冲突的锁
alter语句会加表锁吗?5.6之前 执行DDL语句的时候,整个表都会堵塞。5.6引入了OnlineDDL,允许在执行DDL的时候,DML同时进行。
DDL算法
COPY算法(早期)
DDL操作下会生成临时表,将原表数据复制到新表中,期间会堵塞DML。
INPLACE 算法(5.6)
nplace-no-rebuild :对二级索引的增删改查、修改字段长度、重命名列名都不需要重建原表
inplace-rebuild:修改主键索引、增加删除列、修改字符集、创建全文索引等都需要重建原表。
INSTANT算法(8.0.1)
个别操作可以直接修改表的元数据,省掉了重建原表的过程
意向锁
意向锁是为了在加表锁前,不必逐行检查是否加了行锁,而是通过表级意向锁快速判断是否有冲突。
行级锁
行锁
- 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排它锁
- 排他锁(X):允许获取排他锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁
注意事项
- 针对唯一索引进行检索时,对已存在的记录进行等值匹配时,将会自动优化为行锁
- lnnoDB 的行锁是针对于索引加的锁,不通过索引条件检索数据,那么 InnoDB 将对表中的所有记录加锁,此时就会升级为表锁
有排他就堵塞
间隙锁
用于防止幻读,对表中的一个范围进行锁定(20,25)(25,30)
临键锁
是间隙锁和行锁的组合,用于防止幻读、修改或删除范围内的行(20,25)25
事务
四大特性
一致性,隔离性,持久性,原子性
隔离级别
读未提交RU
脏读、幻读、不可重复读
读已提交RC
幻读、不可重复读
可重复读RR
幻读
串行化
脏读、幻读、不可重复读
- 脏读: 事务A可以查询到事务B为提交的数据
- 不可重复读:事务A可以查询到事务B已提交的数据(修改结果,不一致)
- 幻读:事务A可以查询到事务B已提交的数据(新增,结果集不同)
MVCC
多版本并发控制+为解决幻读而生
实现依赖于Undolog+ReadView
当前读
读取记录的最新版本
select ... for update
快照读
普通的select语句
- rc每一次查询,都会产生一个快照读
- rr开启事务后的第一个select,才会产生一个快照读
隐藏字段
创建表后会有三个个隐藏字段
- db_trx_id 事务ID
- db_roll_ptr 回滚指针
- db_row_id 没有指定主键,默认的主键
undolog
维护了一个数据的多个版本
- 当执行insert语句产生的insert语句 只在事务提交的时候有用,事务提交后就没用了,可以删除。
- update或delete语句不仅仅是提交 在MVCC中可能会用到。
readview
- 读视图
三大日志
undolog(回滚日志)
作用
事务回滚和解决幻读问题
- 记录数据被修改前的neritic,提供回滚操作,保证原子性
- 用于MVCC
原理
问题
redolog(重做日志)
作用
当系统出现异常的时候,可以快速恢复数据。对应四大特性中的持久性。修改了,即使发生系统奔溃,数据也应该被保留,支持后续恢复。wal日志先写的体现
原理
一个事务在运行过程中是不会直接进行操作磁盘上的数据的,而是有一个bufferpool的缓存池,首先会修改bufferpool的数据,同时写入redologbuffer中,当事务提交的时候,会通过已经设置好的刷盘策略写入redolog文件中。
问题
redolog写入的是什么文件
记录的是哪个页发生了哪些物理变化。类似哪个表空间,哪个页,偏移量和修改的值。
为什么不直接写入磁盘 idb文件中
一次事务提交大部分操作的是数据基本都不在同一个页中,在磁盘中是随机的,带来的损耗和时间大,但是写入一个新的文件是顺序写。
刷盘策略有哪些
刷盘策略是指从redobuffer中写入redolog文件中的过程
- 定期刷盘
- 提交时写入
- 写入系统缓存中,由系统去操作
redolog日志
redolog日志是一个环形的结构,多个文件,一个检查点 一个写入点。当写入位置追上检查位置的时候,会发生堵塞,事务卡在提交。
binlog(归档日志)
作用
保存所有执行过的修改数据的语句,当不小心删除了表中的数据,可以通过 binlog 来恢复。
二阶段提交
解决redolog和binlog 一致性
先redolog prepare 然后binlog 然后redolog commit
评论