MySQL的索引和锁知识点

162 阅读3分钟

MySQL架构

  • 目前主流的架构大致如下,各种封装的客户端连接到MySQL连接池,账户密码式登录。
  • SQL语句经过优化器优化后被执行器执行,并调用存储引擎获取数据。
  • 主流的存储引擎基本都是InnoDB,虽然也还有MyISAM和Memory等其他存储引擎,但基本现在建表都不用了。
  • 具体的数据、索引以文件形式存储在磁盘中;执行过程会生成日志文件,并依靠日志系统实现事务执行等其他功能。


MySQL锁类型

从数据层面划分

  • 表锁
  • 行锁

从功能划分

  • 共享锁

  • 共享锁即读锁

  • 排他锁即写锁

    delete/update/insert语句会自动加上排它锁。 手动加排他锁 select * from student where id=1 FOR UPDATE;

加锁场景

  • 哪些场景下我们的MySQL会对表进行加锁?

  • 为表创建索引时会锁表。所以对于线上生产环境,加索引的时机需要选好,并且大表加索引需要慎重,防止锁表造成线上生产事故。

加锁机制


MySQL事务实现原理

MySQL事务的特征

  • Atom 原子性
  • Consistent 一致性
  • Isolation 隔离性
  • Durability 持久性

事务隔离级别

隔离级别 描述
Read-Uncommit 读未提交
Read-Committed 读已提交
Replicate Read 可重复读
Serialize 串行执行

日志系统

  • redo log

    • redo log 记录事务执行成功后的值,并持久化,当事务执行失败,需要恢复数据时,只需要将redo log中的记录重新执行就能恢复正确数据。所以redo log保证事务的持久性。
  • undo log

    • undo log 可以理解为事务提交前会在undo log中先写入一条对应的回滚SQL,当事务需要回滚时直接执行回滚SQL。因此undo log保证事务的原子性,即操作要么成功要么失败并回滚到最初状态。
  • bin log

    • 利用binlog恢复数据。

赃读

  • 两个事务,其中一个事务读取了另外一个事务未提交的数据

幻读

  • 同一个事务,读取同一记录两次,两次结果不一样
  • 如何解决幻读问题:事务读取的时候,不允许更新数据

不可重复读

  • 一个事务在读取某些数据时,数据已经发生了变化,或者已经被删除了,这种现象就叫不可重复读。

  • 用哪些锁去解决上述问题


MVCC

  • InnsoDB在每行记录后面保存两个隐藏的列,分别保存了这个行的创建时间和行的删除时间。这里存储的并不是实际的时间值,而是系统版本号,当数据被修改时,版本号+1。

  • 在读取事务开始时,系统会给当前读事务一个版本号,事务会读取版本号<=当前版本号的数据,此时如果其他写事务修改了这条数据,那么这条数据的版本号+1,从而比当前读事务的版本号高,读事务自然就读不到更新后的数据了。


索引类型

  • 索引类型
  • 唯一索引
  • 普通单值索引
  • 联合索引
  • 组合索引
  • 聚簇索引
  • 全文索引
  • 二级索引

索引数据结构的选型逻辑

  • HashTable

    • 内存存储引擎
  • B Tree/B+ Tree

    • B+树与B树的区别是B+树的非叶子节点不存储数据,而B树会存储实际数据,

索引构建流程

索引优化案例

  • 最左前缀匹配原理

  • 全文索引优化like

  • 从Spring Transaction 到MySQL的事务过程


参考文章

  1. liuming.cool/2020/01/10/…
  2. blog.csdn.net/tongdanping…