连接层

服务层

引擎层

文件层

是CP,还是AP的?

在同一张表,唯一索引字段的值都是唯一的

可以为null,且可以为多个null值

通常是非聚簇索引

为什么说通常呢?

因为我们可能忘了设置主键索引,那么MySQL就会默认选择一个唯一非空索引作为主键,如果没有,就

会使用row_id

是怎么保证唯一性的?

和主键索引的区别

是否可以为null

是否回表

是否可以有多个

索引类型不同

是否可以为外键

缺点

没有银弹,插入时需要判断是否存在存在

更新索引列字段时,需要先删除原记录,再判断新插入的值是否唯一,再插入(InnoDB帮我们自动完

成的)

这里说的是b+树索引结构的变化

d字段,建了一个索引D,允许为null,那么当 select * from table where d is null,select * from table where d is not null这两条sql,在唯一索引和普通索引下有什么区别?

首先我们可以把索引中的null看成最小值

那么无论是前者还是后者都可以从左开始扫描。但是全表扫,还是索引扫,得看查询优化器的评估或者是

否可以命中索引覆盖

五分钟搞懂MySQL索引下推 - 三分恶 - 博客园

mysql5.6引入的一种索引优化手段,它就是说MySQL在执行SQL时,会把判断条件传给存储引擎,然后在查

查询过程中直接过滤掉不符合的记录,减少回表产生的磁盘IO

下推的意思是什么??

首先我们要清楚没有这个机制下,MySQL是怎么查询的?

1.存储引擎读取索引记录

2.回表拿到行记录

3.把行记录交给<font style="color:rgb(199, 37, 78);">Server</font>层去检测该记录是否满足<font style="color:rgb(199, 37, 78);">WHERE</font>条件

那么下推的意思就是说 原先服务层做的事情交给引擎层去做

有了该机制后

1.存储引擎读取索引记录

2.根据索引的字段判断是否可以根据where条件过滤掉部分不符合的记录,有就过滤,没有就拉倒。拿到

结果主键

3.回表

4.把行记录返回给server,再做其余where字段的判断

MySQL8.0引入的一种索引优化手段。它就是说当我们不遵循最左匹配原则时,即缺失聚合索引的最左列,

这个机制会通过枚举的方式帮我们补齐最左列

适用条件

0.查询的字段必须是索引中的列

1.最左列的区分度不大,如果太大,枚举的效率就很低,那么就没意义了。所以到底要不要用还得查询优

化器抉择

2.查询时只能依赖于一张表

3.不可以用group by,DISTINCT

4.表T至少有一个联合索引,但是对于联合索引(A,B,C,D)来说,A和D可以是空的,但B和C必须是

非空的。

把数据和索引分开存储,不影响数据的存储结构,而是单独新建一张索引表

非叶子节点是索引,叶子节点存的是索引+主键ID

在InnoDB中,聚簇索引指的就是非叶子结点存的是索引,叶子节点存的是行记录

它会按照主键的逻辑顺序将行数据存储在磁盘,这也使得行的物理存储顺序和主键的逻辑顺序一样,查询起来

非常快

mysql InnoDB无页级锁

InnoDB的设计初衷为高并发,在实现的过程中做了很多减少锁粒度的工作。故锁升级这一概念违背了其设计理念

InnoDB引擎特有的

记录锁

锁住某行记录,分为读写锁,事务提交后自动释放,例如select * from table_name where id = 1 for update;就给id=1这行记录上了写锁

间隙锁

锁住行与行之间的间隙,防止其它事务在间隙中插入数据,产生幻读,间隙锁是不互斥的(如果涉及到记录锁或者临键锁,还是会互斥阻塞),两个事务可以拥有同一段间隙的间隙锁,但要插入数据时发现这段间隙被其它事务锁上了就插不了了。间隙锁是为了解决幻读,防止其它事务在区间内插入数据

临键锁(间隙+记录锁)

加临键锁的时候是先加间隙锁,后加记录锁,这就有可能出现加间隙锁能成功,加记录锁被阻塞,然后间隙锁与其它事务发生死锁

前开后闭区间,锁住某行以及这一行之前的间隙,如(1, 3],锁住3这一行和1到3行之间的间隙,因为有记录锁,会产生读写互斥,间隙锁之间不互斥

插入意向锁

插入意向锁是一个间隙锁,但这个间隙锁实际上锁住的不是一个区间,而是区间中插入的那个点,所以算是一种特殊的间隙锁,插入意向锁和插入意向锁会互斥,即两个事务可以在同一个区间插入,但不能在同一个区间上相同的点插入;插入意向锁与间隙锁互斥,即插入的点所处的区间不能被其它事务的间隙锁锁住

当事务要插入记录时,判断是否有与插入意向锁冲突的锁,如果有,加插入意向锁,进入锁等待,如果没有,什么锁都不加,直接插入数据,就是说不加插入意向锁!

插入完成后,会给插入的这个数据上个记录锁(其实不会上记录锁,这是个隐式锁,后面会介绍),防止其它事务更改这条数据,直到事务提交后释放这个记录锁

当间隙中存在间隙锁,与插入意向锁冲突

当间隙中存在插入意向锁,间隙锁阻塞

当间隙中存在插入意向锁,但要插入的点和自己不同时,不阻塞(插入意向锁是在间隙中锁住某个点)

对整个表加的锁

意向锁

为什么要有这锁?

如果A对表中的一行上了写锁,这时B对表上了写表锁,表示表里面的每一行都可以修改,这时就矛盾了

虽然B在申请表锁你可以遍历每一行,但这不太现实。

故意向锁就是为了解决这种不同锁粒度之间的并发性问题,有了这锁后,在给表上表锁,就可以直接判断

是否有事务对表中的数据进行操作

意向锁不是锁资源,只是一个通知,且锁是由mysql管理的

上行级共享锁时会先给表上一独占意向锁,上行级独占锁时会先给表上一共享意向锁

意向共享锁和意向独占锁不冲突,但他两和表锁互斥(共享读表锁和意向共享锁不互斥)

元数据锁(字典锁)

锁定表的结构数据,防止DDL和DML、DQL起冲突

当进行CURD时,就会给表上 元数据读锁

当进行DDL时即想要修改表的结构时,就会给表上 元数据写锁

元数据锁在事务提交后自动释放

申请元数据锁的事务会进入一个队列,如果出现了申请元数据写锁的请求,就会阻塞后续的事务

AUTO-INC锁

保证自增主键能连续自增的锁

当事务执行insert的时候就会给表上这个锁

5.6之前,这个锁的粒度比较大,当事务提交时才会释放,即即使insert后无insert操作了,也不会释放,直到

事务提交

5.6后,事务中的每一次insert结束后就会释放锁( 插入多行数据时,会加一次自增锁并一次性分配一段连续

ID )

表级排他or共享锁

lock table read 给表上读锁

lock table write 给表上写锁

unlock table 释放当前会话中拥有的所有的锁,会话取消也是会自动释放