整体架构
MySQL可以分为Server层和存储引擎层两部分。
不同的存储引擎(不同的表可以设置不同的存储引擎)共用一个Server层(从连接器到执行器)。
查询流程
连接器
Command列显示Sleep表示空闲连接。
如果客户端太长时间没动静,那么连接器会自动将它断开,由参数wait_timeout控制,默认值是8小时。
查询缓存
针对查询请求,先查询缓存(key是查询的语句,value是查询的结果),缓存中没有时再执行语句,执行结果存入缓存。
缓存弊大于利
更新表后,清空该表上所有查询缓存。针对频繁更新场景,查询缓存的命中率低。
弃用缓存
从MySQL 5.7.20开始,不推荐使用查询缓存,在MySQL 8.0中删除
更新流程
因性能问题而使用redolog
如果每次更新都通过磁盘先找到记录再更新,那么IO成本高。
先写日志,再写磁盘。
更新记录时,InnoDB先把记录写到redolog(重做日志,InnoDB引擎独有的日志),更新内存,InnoDB引擎会在空闲时候把这个操作更新到磁盘。
InnoDB的redolog(类似于黑板)是固定大小的,从头开始写,写到末尾又回到开头继续写。
checkpoint是即将擦除记录的位置,向后推移并循环,擦除记录前把记录更新到磁盘。
write pos是当前记录位置,向后推移并循环,写到3号文件末尾后回到0号文件开头。
write pos和checkpoint之间是空白部分,用于记录新的操作。
如果write pos追上checkpoint,那么表示redolog满了,先擦除记录再后移checkpoint。
redolog重做日志与binlog归档日志区别
1.redolog是InnoDB引擎独有的;binlog是MySQL的Server层实现的,所有引擎都可以使用。
2.redolog是物理日志,记录“在某个数据页上做了什么修改”;binlog是逻辑日志,记录语句的原始逻辑,例如“给ID=2这一行的c字段加1 ”。
3.redolog是循环写的,空间固定会用完;binlog是追加写入的,binlog文件写到一定大小后切换到下一个,不覆盖以前的日志。
4.redolog用于MySQL重启恢复,binlog用于MySQL备份恢复。之所以不用binlog来恢复,是因为逻辑日志binlog需要转成物理日志redolog,耗时。
update具体流程
执行update T set c=c+1 where ID=2;
1.执行器通过InnoDB来取ID=2这一行,因为ID是主键,所以InnoDB搜索B+树找到这一行。如果这一行所在的数据页在内存中,那么直接返回给执行器;否则,从磁盘读入内存后返回。
2.执行器把这个值加1。
3.InnoDB把这行新数据更新操作记录到redolog,redolog进入prepare状态。
4.执行器生成这个操作的binlog,把binlog写入磁盘。
5.执行器通过InnoDB来提交事务,InnoDB把redolog改成提交状态,更新完成。
两阶段提交
prepare阶段写入redolog,commit阶段写入binlog。
事务未提交,MySQL重启,redolog和binlog都没有了,事务回滚。
两阶段提交目的是,确保redolog和binlog逻辑一致。
双1配置:redolog(innodb_fush_log_at_trx_commit)和binlog(sync_binlog)在事务提交后同步到磁盘。
事务提交之后,redolog先刷盘,binlog再刷盘。
事务提交之前,MySQL异常重启后,SQL执行没生效。
事务提交之后,redolog超过binlog部分会回滚,因为缺少binlog无法完成主备复制。