查询语句执行过程:
连接器:
在客户端与mysql服务端建立TCP连接之后,连接器会验证用户身份,之后的所有请求全都是按照这个时候验证的身份权限进行的,所以更新用户身份证之后重新连接才会更新权限
mysql在执行过程中临时使用的内存是管理在连接对象里的,所以这个连接如果一直没断的话,占用内存就会持续上涨
查询缓存:
缓存是以k-v的形式缓存的,所以如果执行语句有任何不同的话都是查不到缓存的
且如果表发生变化的话,建立的所有缓存都会删除
分析器:
词法分析:将输入的字符序列分解成有意义的标记(关键字、标识符、操作符或常量等)
语法分析:在词法分析的基础上,检查这些标记是否遵循sql的语法规则,构建抽象语法树
优化器:
会对逻辑进行重写,生成多种执行方法,评估多种执行方法,选择最优的一条
逻辑优化(查询重写):
谓词下推,尽早执行where,减少中间数据量
视图重写,将视图展开为实际的sql查询
子查询优化,子查询转换为连接join
常量折叠,提前计算可以确定的表达式
OR转UNION,便于使用索引
物理优化(决定如何执行sql):
是否使用索引以及使用什么索引
表的连接顺序
连接算法
是否使用索引排序,是否需要额外排序
执行器:
调用存储引擎,真正执行查询,返回结果
三大日志:
redolog:
在更新的时候,需要把新的值写到磁盘上,但是每次io操作会造成性能下降
所以当需要更新的时候,innoDB会把要更新的值写到redolog中,然后只更新内存
定期将redolog中的内容写到磁盘中
redolog在内存中是一组环形数组,有两个标志位——write pos和check pos
如果更新的话就写在内存,同时记录到redolog并把write pos后移
如果更新到磁盘,把redolog中的内容写到磁盘上,然后check pos后移
这样即使数据库崩溃了,但是redolog还在,仍然可以根据redolog来恢复之前操作的数据
作用:
保证事务的持久性:事务一提交就把redolog的内容写到磁盘上,保证事务的持久性
提高性能:减少IO操作,支持多线程并发写入
崩溃恢复:
记录的内容:
是物理日志,记录的是对数据做的改动
对数据页的具体修改:数据页编号、修改前后的值、修改类型(插入、更新、删除)
binlog:
是server层的逻辑日志,记录的是逻辑语句
主要作用是:主从复制,同时也有数据恢复和审计追踪的作用
记录的内容:
- STATEMENT:记录的是 SQL 语句本身。优点是日志量较小,但某些情况下可能导致主从数据不一致(如依赖于当前时间戳或随机数的查询)。
- ROW:记录的是每一行的具体变化(增删改)。这种方式更加精确,能够确保主从数据的一致性,但产生的日志量较大。
- MIXED:默认模式,结合了 STATEMENT 和 ROW 的优点。在存在数据不一致的时候自动切换为 ROW 格式以保证数据一致性。
数据恢复:将数据恢复到指定日期之前最近的一次全量备份,然后执行全量备份之后的binlog,直到指定日期即可
redolog + binlog ——两阶段提交:
无论是先写redolog还是再写binlog,如果要恢复数据,两个日志不一致的话都会造成数据不一致,主要是为了保障分布式数据库的数据一致性
所以两阶段提交:
写完redolog之后redolog为prepare状态,写binlog,redolog为commit状态
mysql事务:
事务是在存储引擎层实现的
当多个事务同时执行的话就可能造成数据不一致的问题:
脏读、丢失修改、不可重复读、幻读
为了解决多个事务对共享数据的操作安全性,提出不同的事务隔离级别:
读未提交,读已提交,可重复读,事务串行化
mysql中的事务并发控制方式实际上只有两种:锁和MVCC
锁:读写锁,可以实现读读并行,但是不能读写、写写并存
根据粒度可以分为表级锁和行级锁
MVCC:多版本并发控制方法,将一份数据存储多个版本,事务只能看到一份数据自己应该看到的版本
MVCC的实现方式依赖:隐藏字段、read view、undo log
隐藏字段:
在innoDB中,每一行数据都包含几个隐藏字段:
DB_ROW_ID: 行id,插入新行单调递增
DB_TRX_ID: 事务id,记录最后一次插入或更新该行的事务id,每次对数据进行修改时,都生成一个新的版本,将这个字段更新为当前事务的id
DB_ROLL_PTR:指向undo log的指针
read view:
是一个快照,记录了系统中所有活跃事务的id列表(已经启动但是尚未提交的事务),通过比较DB_ROW_ID和read view,可以决定这个版本的数据是否可见
DB_ROW_ID<read view中最小活跃事务id,说明这个版本是在当前事务开始前就完成的,可见
DB_ROW_ID在read view的活跃事务id列表中,说明这个版本是未提交的事务创建的,不可见
innoDB的MVCC和read view机制是行级可见性控制,每个数据行的可见性是独立判断的
对于某一行的话不可能出现后面的事务提交了前面的事务还没
undo log:
当一个事务对数据进行修改时,innoDB不仅会修改数据,还会在undo log中记录如何撤销这些更改
通过undo log可以回滚事务
在MVCC时,当有其他事务需要访问旧版本数据时,可以通过undo log找到数据历史版本
undo log分为两种:
insert undo log:专门记录插入操作的undo信息,事务提交之后可以直接删除
update undo log:记录更新或删除操作的undo信息,一直保留到没有事务需要相关旧数据
如果事务很长的话,就会导致会保留很多undo log不能删除,就会占用大量内存空间
读:读的是数据快照
写:innoDB在写数据的时候会对记录加锁,在获得行的写锁之后才能进行修改,事务提交或者回滚之后才能会把这个行的写锁释放,其他事务才能继续修改这个行
所以MVCC主要用于“一致性非锁定读”,提升读操作的并发性能,对于写的话由于要获得写锁,所以都需要等其他事务提交之后才能进行写,所以都是基于最新版本的数据
那其他事务在读这一行的时候首先会通过这一行的隐藏字段和read view来判断可见性:
1.如果小于当前活跃的最小事务id,可见
2.如果不在活跃列表,则以提交,可见
3.否则的话就根据隐藏字段找到undolog,读之前的版本