县网站建设,搜一搜站长工具,wordpress搜索调用,工业设计考研比较好的学校Server 层 存储引擎层 总流程 查询语句 连接器 查询缓存 分析器 优化器 执行器 更新语句 redo log#xff08;节省的是随机写磁盘的 IO 消耗#xff08;转成顺序写#x… Server 层 存储引擎层 总流程 查询语句 连接器 查询缓存 分析器 优化器 执行器 更新语句 redo log节省的是随机写磁盘的 IO 消耗转成顺序写 InnoDB 引擎 物理日志 循环写 binlog server层 逻辑日志 追加写入 两阶段提交 为了知道mysql 中一条 sql 语句是如何执行的先讲一下 mysql 的宏观分层以及如何执行查询语句. MySQL 宏观上分为 Server 层 和 存储引擎层 MySQL 通过 server 层调用存储引擎层操作数据返回结果Server 层又可以分为
连接器分析器优化器执行器
连接器负责跟客户端建立连接、获取权限、维持和管理连接。
分析器先会做“词法分析”。你输入的是由多个字符串和空格组成的一条 SQL 语句MySQL 需要识别出里面的字符串分别是什么代表什么。做完了这些识别以后就要做“语法分析”。根据词法分析的结果语法分析器会根据语法规则判断你输入的这个 SQL 语句是否满足 MySQL 语法。
优化器是在表里面有多个索引的时候决定使用哪个索引或者在一个语句有多表关联join的时候决定各个表的连接顺序。
执行器会根据表的引擎定义去使用这个引擎提供的接口。示例
mysql select * from T where ID10;
比如我们这个例子中的表 T 中ID 字段没有索引那么执行器的执行流程是这样的
调用 InnoDB 引擎接口取这个表的第一行判断 ID 值是不是 10如果不是则跳过如果是则将这行存在结果集中调用引擎接口取“下一行”重复相同的判断逻辑直到取到这个表的最后一行。执行器将上述遍历过程中所有满足条件的行组成的记录集作为结果集返回给客户端。
至此这个语句就执行完成了。 查询语句的那一套流程更新语句也是同样会走一遍。与查询流程不一样的是更新流程还涉及两个重要的日志模块它们正是我们今天要讨论的主角redo log重做日志和 binlog归档日志。
redo log
如果每一次的更新操作都需要写进磁盘然后磁盘也要找到对应的那条记录然后再更新整个过程 IO 成本、查找成本都很高。
当有一条记录需要更新的时候InnoDB 引擎就会先把记录写到 redo log里面并更新内存这个时候更新就算完成了。同时InnoDB 引擎会在适当的时候将这个操作记录更新到磁盘里面。
InnoDB 的 redo log 是固定大小的满了时不能再执行新的更新。由参数 innodb_log_file_size 和 innodb_log_files_in_group 决定。 有了 redo logInnoDB 就可以保证即使数据库发生异常重启之前提交的记录都不会丢失这个能力称为 crash-safe。
change buffer
当需要更新一个数据页时如果数据页在内存中就直接更新而如果这个数据页还没有在内存中的话InnoDB 会将这些更新操作缓存在 change buffer 中这样就不需要从磁盘中读入这个数据页了。在下次查询需要访问这个数据页的时候将数据页读入内存然后执行 change buffer 中与这个页有关的操作。change buffer 在内存中有拷贝也会被写入到磁盘上。
将 change buffer 中的操作应用到原数据页得到最新结果的过程称为 merge。除了访问这个数据页会触发 merge 外系统有后台线程会定期 merge。在数据库正常关闭shutdown的过程中也会执行 merge 操作。
change buffer 用的是 buffer pool 里的内存因此不能无限增大。change buffer 的大小可以通过参数 innodb_change_buffer_max_size 来动态设置。这个参数设置为 50 的时候表示 change buffer 的大小最多只能占用 buffer pool 的 50%。 因为 merge 的时候是真正进行数据更新的时刻而 change buffer 的主要目的就是将记录的变更动作缓存下来所以在一个数据页做 merge 之前change buffer 记录的变更越多也就是这个页面上要更新的次数越多收益就越大。因此对于写多读少的业务来说页面在写完以后马上被访问到的概率比较小此时 change buffer 的使用效果最好。
binlog
redo log 是 InnoDB 引擎特有的日志而 Server 层也有自己的日志称为 binlog归档日志.这两种日志有以下三点不同。
redo log 是 InnoDB 引擎特有的binlog 是 MySQL 的 Server 层实现的所有引擎都可以使用。redo log 是物理日志记录的是“在某个数据页上做了什么修改”binlog 是逻辑日志记录的是这个语句的原始逻辑比如“给 ID2 这一行的 c 字段加 1 ”。redo log 是循环写的空间固定会用完binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个并不会覆盖以前的日志。 执行器和 InnoDB 引擎在执行这个简单的 update 语句时的内部流程
执行器先找引擎取 ID2 这一行。ID 是主键引擎直接用树搜索找到这一行。如果 ID2 这一行所在的数据页本来就在内存中就直接返回给执行器否则需要先从磁盘读入内存然后再返回。执行器拿到引擎给的行数据把这个值加上 1比如原来是 N现在就是 N1得到新的一行数据再调用引擎接口写入这行新数据。引擎将这行新数据更新到内存中同时将这个更新操作记录到 redo log 里面此时 redo log 处于 prepare 状态。然后告知执行器执行完成了随时可以提交事务。执行器生成这个操作的 binlog并把 binlog 写入磁盘。执行器调用引擎的提交事务接口引擎把刚刚写入的 redo log 改成提交commit状态更新完成。
将 redo log 的写入拆成了两个步骤prepare 和 commit这就是两阶段提交。
推荐阅读
一条 SQL 更新语句如何执行的
MySQL 事务的原理以及长事务的预防和处置
InnoDB索引优化
一条 sql 语句可能导致的表锁和行锁以及死锁检测