我是一条SQL语句 :)
前言 : 今天本来计划好了和朋友一起出去晒晒太阳,结果他临时有事情,我被活生生的拉到他办公室里,也不知道做些什么,就拿了他办公室里一瓶红酒独饮,喝着好生无聊,突然想起自己从来没写过博客,就尝试的写了这么一篇。 本文简介了一条SQL语句在MYSQL(InnoDB)下的执行过程,算是个小尝试吧。
先简单的介绍下MySQL Server层的各个"零件"
连接器
管理连接,验证权限。简单的扩展一下: 客户端一旦建立连接后,即使中途更换了权限,也不会影响。
查询缓存
key-value 查询缓存对,如果查询语句匹配则直接返回 。简单的扩展一下:如果在某个表上有任意更新,会清空这个表上全部缓存,所以往往弊大于利。MySQL 80 版本将此 "零件"删除。
分析器
词法分析,语法分析(也就是对SQL语句的解析)
优化器
在SQL语句WHERE后有多个索引时优化器负责决定使用哪个索引,确定执行计划。(这个"零件"如果展开说得要单独得文章展开说明了,如果再有雅兴的话,那下一篇博客详细说明)
执行器
这个我认为是有必要多说几句得:我们通过分析器知道你要做什么,通过优化器知道该怎么执行,执行器就开始执行了。我会以一条查询SQL示例
select * from plc_main where policyno = '1'
- 调用 InnoDB 引擎接口取这个表的第一行,判断 policyno 值是不是 1,如果不是则跳过,如果是则将这行存在结果集中;
- 调用引擎接口取“下一行”,重复相同的判断逻辑,直到取到这个表的最后一行。
- 执行器将上述遍历过程中所有满足条件的行组成的记录集作为结果集返回给客户端。
再来引入一些重要的"角色"
binlog
Server 层自己的日志,你可以叫它归档日志。这个日志记录的是逻辑日志,有两种模式,statement 格式的话是记 sql 语句,row 格式会记录行的内容。是用来做数据恢复的。
redo log
redo Log是InnoDB 引擎特有的日志,你可以叫他重做日志,。这个日志是物理日志,记录的是某个数据叶上做了什么修改,不记录更新后的状态。他的出现节省了写磁盘IO成本,也给数据库出现异常时增加了crash-safe能力。
change buffer
我们一般叫他写缓存,我在这里用一条更新sql示意:
insert into p(id,k)values(id1,k1)
- 这个数据K索引在内存叶中,直接更新内存;
- 这个数据K索引不在内存叶中,就在内存的 change buffer 区域,记录下“我要往xx内存页插入一行” 这个信息 。
- 将上述两个动作记入 redo log 中
bufferpool
这个见名知意思,这个就是缓冲池了。他的作用就是避免每次访问磁盘,以加速数据的访问。一般每个索引的根节点和热点数据都会在bufferpool存放。
undo log
这个是为数据库提供了回滚和多个行版本控制,他记录的是逻辑日志,你可以这样认为:当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录。
我在这里很粗略的介绍了下这些"角色"们,其实每一个"角色"都可以单独拿出来单独写一篇博客,如果你感兴趣,可以逐个点拉开去深入。
好了我们开始了一条sql更新语句
update plc_main set createdate = sysdate where policyno = '2'
*(在这里把policyno当成了主键索引)
- 执行语句前要先连接数据库,这是连接器干的活;
- 如果我们开启了查询缓存时,会把这个plc_main 表上所有缓存结果都清空
- 接下来,分析器会通过解析知道这是一条更新语句
- 然后优化器决定要使用 policyno 这个索引
- 执行器先找引擎取提供的接口获取 policyno =2 这一行,如果这一行在内存(bufferpool)中就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回
- 如果不在内存中 ,且内存满了,需要淘汰最不长使用的内存页,这涉及到了淘汰脏页(数据页与磁盘记录的不一致)
- 执行器拿到引擎给的行数据更改了createdate的值,再调用引擎的接口写入这行新数据
- 引擎将这个这个行更新到内存中,同时将这个更新操作记录到 redo log 里面 (redo log满了的清空我们就不做讨论了)
- 这时候 redo log是prepare状态, 随后告诉执行器我们执行完了可以随时提交事务
- 执行器生成这个操作的 binlog,并把 binlog 写入磁盘
- 执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交commit状态,更新完成。
至此这一条sql语句结束了,有点虎头蛇尾了,但是整瓶喝完已经晕晕乎乎的写不下去了,朋友说我脸红了, 还给我泡了杯茶 。
溜了溜了,如果想一起交朋友认识的 可以加我微信 : 18800205228 . 拜拜喽
转载:https://blog.csdn.net/weixin_43933804/article/details/115572820