MySQL 笔记

语句执行过程

索引

1.为什么用B+树?

可以通过最左匹配原则范围查询,层数少,减少读磁盘的次数 最好在离散度较高的数据上做,如果离散越低可能会不使用索引

2.聚集索引

InnoDB 以主键顺序存放数据,索引结点即数据位置 除主键外,其它索引不是聚集索引 如果没有主键,则选第一个唯一索引,如果没有唯一索引,则选一个自有的 rowId 做主键

3.回表

InnoDB中,非主键索引的叶子节点存放的主键索引id,通过非主键索引拿到主键索引id,在去主键索引中查到数据。

4.联合索引

最左匹配原则,例如 index(a, b, c) 会创建 index(a), index(a,b),index(a,b,c) 三个索引,只有使用最左侧的key时才会用到

5.覆盖索引

要查的字段本身就在联合索引上,会直接使用覆盖索引中的值 using index,不用加表。为什么不用 select * 就是因为 select * 不会用到覆盖索引。

6.在前面放%一定用不到索引么?

select * from employee where first_name="zhang" last_name="%an"; first_name 有一个索引,那结果会在 Server 层进行过滤,即 using where,所以也是用到索引的。(前题是没有开启索引下推)

7.索引下推

上面的sql如果已经开启了索引下推,那会变成 using index condition 会在存储引擎层进行过滤数据,只有二级索引会有,主键索引不需要

8.为什么不建议用乱序的值做主键索引

因为主键索引是聚集索引,乱序的值会增加页的分裂开销

MVCC

1.ACID

Atomicity 原子性,要么都成功,要么都失败。发生异常要是用到 undolog Consistent 一致性, Isolation 隔离性, Durable 持久性,事务成功,要保存上,使用 redolog,用于做崩溃恢复

2.事务并发的问题及隔离级别

脏读:读到另一个事务未提交的数据 不可重复读:一个事务中读到另一个事务提交了的数据,包括删除 幻读:一个事务读到另一个事务增加的数据。

Read Uncommitted 未提交读 Read Committed 读已提交 Repeatable Read 可重复读 Serializable 串行化

在 InnoDB 中,Repeatable Read 也处理了幻读问题即和Serializable一样。

3.MVCC

Multi Version Concurrency Control 生成一个数据请示时间点的一致性数据快照,并用这个快照来提供一定级别的一致性读取。基于快照,或是读基于版本。 在InnoDB中每一行都有三个隐藏的字列 DB_ROW_ID 行标识 DB_TRX_ID 事务id,或是行版本号,插入或更新行的最后个事务的事务id,自动递增 DB_ROOL_PTR 回滚指针(删除版本)

新数据的 DB_ROLL_PTR 为 NULL, 当有数据更新时,老数据的 DB_ROLL_PTR 会变成当前事务版本号,并新增一个新行。 image.png

在查询数据时,他的只能查到事务版本号小于等于当前版本号的数据,所以避免了幻读。 在更新时,其实会有两条数据,一条删除版本为当版本,一条创建版本为当前版本。 image.png

4.LBCC 锁

Lock Based Concourrency control 在读取数据前,对其加锁,阴止其它事务对数据进行修改。

  1. 共享锁,读锁,行锁,都能访问到数据,但是只能读不能修改。 加锁方式: select * from table where id=1 LOCK IN SHARE MODE; 释放锁: commit/rollback

  2. 排它锁,写锁,行锁,加锁后共享锁和其它排它锁都不能得到锁。 加锁方式: delete/update/insert 默认加上排它锁 select * from table where id=1 FOR UPDATE;

  3. 意向共享锁和意向排它锁 和前两个一样,但都是表级别的锁。且不能用户手动操作。是一个标志。 当有一个表有行锁时,就会有一个意向的表锁。以防止加表锁时为了检查是否有行锁而进行全表扫描。

  4. 锁定了什么?

  • 在没有主键索引的表中,读锁 where id = 1 会阻塞 读where id = 2
  • 在有主键索引的表中,读锁 where id = 1 不会阻塞 读 where id = 2
  • 在即有主键id和唯一索引name的情况下,读 where id=1 会阻塞同行的 where * name = 'zhangsan'

MySQL 中的锁,锁的是索引 如果不设主键,会用默认的rowID当主键,所以会全表扫描,锁聚集索引。所以看起来像锁表了。

如果用唯一索引,锁唯一索引会指向主键索引,所以在锁了唯一索引后会去锁主键索引。

  1. 区间的划分 image.png

  2. 记录锁 Record Lock 唯一性索引(唯一/主键)等值查询,精准匹配,只锁定一条记录。

  3. 间隙锁 GapLock 记录不存在,会锁定这个间隙。只在可重复读事务隔离级别中存在 image.png

  4. 临键锁 Next-Key Lock 注意是左闭右开的 image.png