1.基础架构——查询语句执行流程
连接器:负责和客户端建立连接,获取权限,维持和管理连接。一般都用长连接,wait_timeout控制连接的时长,默认8小时,但长连接在连接过程中,不会释放临时使用的内存等资源,长期以往,可能导致OOM。解决方案:定期断开长连接,或者mysql_reset_connection 来重新初始化连接资源(5.7版本)。
查询缓存:拿到查询请求后,会先看缓存。MySQL之前执行过的语句及其结果可能会以 key-value 对的形式,被直接缓存在内存中。但是查询缓存失效非常频繁,不建议使用,query_cache_type=0,表示关闭。
分析器:解析SQL语句,词法分析字符串代表的含义,语法分析判断SQL语句是否符合MySQL语法,表,列是否存在等。
优化器:语句执行前,进行方案选择(多表多索引),确定执行的方案。
执行器:执行前,先判断是否有执行权限。然后打开表,根据表引擎的定义去使用提供的接口。用接口去一行一行取表的内容,判断是否符合要求,是则存在结果集中,不是则跳过,直到最后一行。
2.基础架构——更新语句执行流程
流程和查询基本一样,但更新涉及两个日志模块,redo log(重做日志)和binlog(归档日志)。
redo log(InnoDB特有):当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到 redo log里面,并更新内存,这个时候更新就算完成了。同时,InnoDB 引擎会在适当的时候,将这个操作记录更新到磁盘里面。write pos当前写的位置,checkpoint当前要擦除的位置。有了redo,InnoDB可以保证即使数据库异常重启之前提交的记录也不会丢失,这个称为crash-safe。innodb_flush_log_at_trx_commit 这个参数设置成 1 的时候,表示每次事务的 redo log 都直接持久化到磁盘。这个参数建议设置成 1,这样可以保证 MySQL 异常重启之后数据不丢失。
binlog(server层):因为最开始 MySQL 里并没有 InnoDB 引擎。MySQL 自带的引擎是 MyISAM,但是 MyISAM 没有 crash-safe 的能力,binlog 日志只能用于归档。而 InnoDB 是另一个公司以插件形式引入 MySQL 的,既然只依靠 binlog 是没有 crash-safe 能力的,所以 InnoDB 使用另外一套日志系统——也就是 redo log 来实现 crash-safe 能力。
两者主要不同点:redo log是InnoDB引擎特有的,binlog是MySQL的Server层实现的,所有引擎都可以使用。redo log是物理日志,记录的“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的,不会覆盖。sync_binlog 这个参数设置成 1 的时候,表示每次事务的 binlog 都持久化到磁盘。这个参数建议设置成 1,这样可以保证 MySQL 异常重启之后 binlog 不丢失。
更新语句的流程:以update T set c=c+1 where ID=2为例,取ID=2这一行,数据在内存中就返回行数据,不在则从磁盘读入内存在返回。然后将这行c值加1,写入新行,将新行更新到内存。写入redolog处于prepare状态,写入binlog,提交事务,redo改为commit状态,更新完成。
题外话:年底了,烦心事就多了,数据库一直是我的薄弱项(本来也就没什么强项),我准备薅一波mysql了。人外有人,与君共勉。
参考资料:丁奇,MySQL实战45讲
部分内容来自网络,如有侵权请联系作者删除。




