SQL的执行流程及死锁查看

231 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情

一、MySQL 体系结构

我们可以把 MySQL 分成三层:连接层(与客户端对接)、服务层(执行操作)、存储引擎层(跟硬件打交道。

image.png

二、一条sql是如何执行的

image.png

一条mysql无论是查询更新还是删除,基本流程也是一致的,都要经过缓存、解析器、优化器的处理,最后交给执行器;区别就在于拿到符合条件的数据之后的操作。

首先,在 InnoDB 里面有个内存的缓冲池(buffer pool)。我们对数据的更新,不会每次都直接写到磁盘上,因为 IO 的代价太大了,所以先写入到 buffer pool 里面。内存的数据页和磁盘数据不一致的时候,我们把它叫做脏页。 InnoDB 里面有专门的把 buffer pool 的数据写入到磁盘的线程,每隔一段时间就一次性地把多个修改写入磁盘,这个就叫做刷脏。

三、如何查看sql语句的加锁情况?

  • 使用infomation_schema数据库中的表获取锁信息
  • 使用show engine innodb status获取当前系统各个事务的加锁信息。

infomation_schema数据库中,有几个表跟锁紧密关联。但是INNODB_LOCKS 和 INNODB_LOCK_WAITS 在MySQL 8.0已被移除,其实就是不鼓励我们用这两个表来获取表信息。推荐使用show engine innodb status

在看死锁日志的时候,我们一般先把这个变量innodb_status_output_locks打开哈,它是MySQL 5.6.16 引入的

set global  innodb_status_output_locks =on;

所谓的死锁,其实就是,我持有你的需要的锁,你持有我需要的锁,形成相互等待的闭环。

查看死锁的一般四个步骤:

  1. show engine innodb status,查看最近一次死锁日志。
  2. 分析死锁日志,找到关键词TRANSACTION
  3. 分析死锁日志,查看正在执行的SQL
  4. 看它持有什么锁,等待什么锁。

四、 一条SQL是如何加锁的呢?

具体根据我们SQL的查询条件是主键、索引或者没有索引,以及隔离级别是(已提交读(READ COMMITED))RC或者可重复读(REPEATABLE READ)RR来判断。

具体分为:

  1. 查询条件是主键,已提交读隔离级别
  2. 查询条件是唯一索引,已提交读隔离级别
  3. 查询条件是普通索引,已提交读隔离级别
  4. 查询条件上没有索引,已提交读隔离级别
  5. 查询条件是主键,可重复读隔离级别
  6. 查询条件是唯一索引,可重复读隔离级别
  7. 查询条件是普通索引,可重复读隔离级别
  8. 查询条件上没有索引,可重复读隔离级别
  9. Serializable隔离级别