一、 mysql的逻辑架构
① 问题解决
如果表 T 中没有字段 k,而你执行了这个语句 select * from T where k=1, 那肯定是会报“不存在这个列”的错误: “Unknown column ‘k’ in ‘where clause’”。你觉得这个错误是在我们上面提到的哪个阶段报出来的呢
答案:分析器,分析器会判断表是否存在,字段是否存在
② 当我们在一张表更新的时候,跟这张表有关的查询缓存都会被清空,所以不建议使用查询缓存。MySQL 8.0 版本直接将查询缓存的整块功能删掉了,也就是说 8.0 开始彻底没有这个功能了,如果不需要这个功能可以将参数 query_cache_type 设置成 DEMAND。
③ 一条select语句执行就是上面的从上往下的流程
二、一条SQL更新语句是如何执行的
更新语句除了上面的逻辑架构层的处理,还需要两个走两个重要的日志模块。
① redo log 重做日志
重做日志是innoDB存储引擎存产生的。
InnoDB 的 redo log 是固定大小的,比如可以配置为一组 4 个文件,每个文件的大小是 1GB
redo log是记录的是页上面的修改,binlog则是类似于sql语句一样的逻辑日志
② 更新流程
当执行一条update语句,数据库会先把更新记录写入到redo log里并更新内存数据,这时候更新就算完成了,同时innoDB会在适当的时候,将redo log批量刷新到磁盘中。这样做的好处就是:操作都在内存,减少磁盘读写的IO。
update T set c=c+1 where ID=2;
执行上面的sql语句流程如下
1) 执行器先到内存中找有没有id = 2的数据,如果没有则到引擎层取出
2) 执行器拿到数据并 计算 c = c+1,得到新的一行数据,再调用新的引擎接口写入这行数据
3) InnoDB存储引擎将数据更新到内存中,同时将这个更新操作写入redo log中,此时redo log处于prepare 状态,然后告知执行器执行完成,随时可以提交事务
4) 执行器生成这个操作的binlog,并把binlog写入磁盘
5) 执行器调用引擎的提交事务接口,引擎把刚刚写入的redo log的状态改成提交(commit)状态,更新完成