索引

分类:索引这一块按照本质分是两种索引,一种是聚集索引一种是非聚集索引。聚集索引就是实际顺序与存储的时候逻辑顺序相同的索引,也就是主键,如果没有主键,那MySQL会把第一个不包含NULL的唯一索引当做聚集索引,都没有,会生成一个隐式聚集索引。非聚集索引可以粗暴的理解为后加的人为的索引,比如name,age之类的。

区别:这两种索引有区别,而这种区别是因为索引的底层结构导致的,索引的底层结构是B+树,B+树的特性就是非叶子节点不存储数据只存储索引,叶子节点存储data也就是数据。
那聚集索引的B+树的样子就是:非叶子节点都是索引,叶子节点直接就是行数据。那非聚集索引的B+树的样子是:非叶子节点是索引,叶子节点是索引对应的主键值,所以需要再跳一次主键的B+树,这个过程就叫做回表。

其他:至于其他派生的索引都是具有一部分功能性,比如唯一索引就是非聚集索引的一种,是用来表示这个数据的唯一性。覆盖索引的意思是在非聚集索引的这个B+树在查找的时候,索引已经囊括了所有要查的数据,也就是Select后面的要查的数据。

特殊:比较特殊的是非聚集索引的联合索引,有最左前缀原则,这个也跟索引的底层的B+树不谋而合。多次谈到B+树结构,下文写一下B+树的优点以及结构

结构:B+树之前说一下B树
B树:矮胖树,一个节点可以有多个子节点,每个节点都会存储数据本身,节点内的键值是排好序的,节点之间也满足排序关系。
B+树
1.数据存储:B+树的Data只存在于叶子节点中,非叶子节点只有索引。(B树什么节点都存数据)由于B+树非叶子节点不存Data,所以每个节点能存的索引更多,树更矮。
2.叶子结点:B+树中有叶子节点有指针,叶子节点之间通过指针链接起来形成一个有序链表(B树叶子节点是相互独立的)
那根据这俩区别,能总结出四个优点:

  1. 数据存储的模式导致树更矮胖,磁盘IO次数少。
  2. 因为Data都存在于叶子节点里面,最差的情况就是一般情况,查询性能稳定。
  3. 叶子节点之间的双向链表,全表遍历效率高。
  4. 叶子节点之间的双向链表,范围查询效率高。

最左前缀原则:看详细的概括
索引失效情况:看详细的概括

锁的出现是因为要处理多并发多线程场景下的并发问题,也就是下面要说的事务。

分类:锁的分类不像索引那样清晰,因为锁既可以锁整个表,也可以锁单行数据,所以大方向分为:表级锁和行级锁。
因为MySQL的存储引擎是InnoDB,所以本文只涉及InnoDB的锁

表级锁有:

  1. 表锁:表级读锁阻止其他操作对表的写,表级写锁其他操作对表的读和写都阻止。
  2. 元数据锁MDL:防止执行CRUD的时候表结构变更(数据库本身会加MDL,不用我们来操作)
  3. 意向锁:意向锁是是为了解决行锁与表锁的冲突设计的,可以快速判断这个表里有没有行锁

行级锁有:

  1. 按照锁的兼容性分为:排他锁和共享锁,也就是X和S锁。
  2. 按照锁的范围分为:

    1. 记录锁:锁单条记录
    2. 间隙锁:锁一个id数字结合,不包括记录本身(前开后开)
    3. 临键锁:记录锁+间隙锁,锁一个范围,包含记录本身(前开后闭)

什么时候加表级锁?当执行UPDATEDELETE的语句的时候,WHERE没有命中索引或者索引失效的时候,就会对全表扫描加锁。
什么时候加行级锁?看详细的概括

三大日志

binlog

逻辑日志,作用是主从复制,全量数据的备份。
追加写,写满一个文件接着创建接着写

写入时机

在每完成一次更新操作之后,生成一条binlog

刷盘时机

什么时候刷盘由sync_binlog参数决定

  • 0:不去强制要求,由系统自行判断何时写入磁盘;
  • 1:每次事务提交后,都要将binlog写入磁盘;
  • N:每N个事务,才会将binlog写入磁盘。

    redolog

缓存机制,以及WAL,看详细的概括。

两阶段提交

看详细的概括。

undolog

逻辑日志,用来回滚的,作用是保障事务的原子性和实现多版本并发控制MVCC

原理

插入:记录插入的主键值就行--------回滚的时候只删除这个主键值对应的记录就行
记录新插入行的主键,回滚的时候根据主键定位并删除

删除:记录这个数据项的所有字段---回滚的时候把内容组成的记录重新插入到表中
这里删除是逻辑删除,删除只是标记为已删除,回滚的时候再置为false

更新:记录主键值和被修改的旧值---回滚的时候把列更新为旧值就行

**1、更新的不是主键:那undolog记录的是主键以及被修改的原始值,回滚的时候根据主键找到这行,再用旧值覆盖新值**
**2、更新的是主键:InnoDB的操作是“删除旧记录+插入新纪录”,所以undolog的记录是针对旧的主键的DELECT型+针对新的主键的INSERT型**

写入时机

在事务没提交之前,先把更新前的数据放到undo log 中

刷盘时机

随 Redo Log 刷盘而持久化。因为undolog本身就算是一个修改操作,修改了。

事务

事务概念本身就是为了保障数据的一致性。

事务的四大特性:

目标实现手段说明
原子性 (A)undo log记录回滚日志,失败了能改回去。
一致性 (C)以上所有 + 业务逻辑最终目标。
隔离性 (I)MVCC (ReadView) + 锁MVCC 负责快照读,锁负责当前读和写。
持久性 (D)redo log保证断电后数据不丢失。

但是并发事务会导致问题,也就是脏读,不可重复读,幻读,解决方式是通过:标准事务隔离级别
级别越高,数据一致性越好,但并发性能可能越低。

  1. 读取未提交:允许读取未提交的数据变更,啥都防不住
  2. 读取已提交:允许读取并发事务已经提交的数据,可以阻止脏读
  3. 可重复读:对同一个字段的多次读取都是一样的,除非是自身修改,阻止了脏读和不可重复读,至于幻读,仍有可能(InnoDB大幅减少)
    一旦事务开始,它就仿佛进入了一个“时间凝固”的快照中*
  4. 可串行化:最高隔离,依次执行,全都防住

MVCC以及快照读,当前读的区别,以及各种细微的问题见 详细的概括。