持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情
一、MySQL 体系结构
我们可以把 MySQL 分成三层:连接层(与客户端对接)、服务层(执行操作)、存储引擎层(跟硬件打交道。
二、一条sql是如何执行的
一条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;
所谓的死锁,其实就是,我持有你的需要的锁,你持有我需要的锁,形成相互等待的闭环。
查看死锁的一般四个步骤:
show engine innodb status,查看最近一次死锁日志。- 分析死锁日志,找到关键词
TRANSACTION - 分析死锁日志,查看正在执行的SQL
- 看它持有什么锁,等待什么锁。
四、 一条SQL是如何加锁的呢?
具体根据我们SQL的查询条件是主键、索引或者没有索引,以及隔离级别是(已提交读(READ COMMITED))RC或者可重复读(REPEATABLE READ)RR来判断。
具体分为:
- 查询条件是主键,已提交读隔离级别
- 查询条件是唯一索引,已提交读隔离级别
- 查询条件是普通索引,已提交读隔离级别
- 查询条件上没有索引,已提交读隔离级别
- 查询条件是主键,可重复读隔离级别
- 查询条件是唯一索引,可重复读隔离级别
- 查询条件是普通索引,可重复读隔离级别
- 查询条件上没有索引,可重复读隔离级别
- Serializable隔离级别