timewind 2020-07-04
一条sql执行的过程:
连接器-------->分析器------->优化器--------->执行器-------->存储引擎 #如下图
不建议使用查询缓存的原因: 如果表有数据更新的话,这张表的缓存都会被清空
特性: innodb的引擎层日志,redo log日志大小时固定的(可通过参数设置),可配置日志个数,可重复写,存储的是脏页,写满后会读入到磁盘(读入的过程称之为刷脏)
一家商店有一个记账板,当赊账顾客多的时候,会临时记录在记账板上,避免频繁去记账本上查找更新对应顾客的信息。等到生意不忙的时候,再将记账板上的信息同步到账本上 。避免高峰期拥堵,提高了工作的效率。
同样,mysql也有这个问题,为了避免更新数据的时候IO成本和查询成本过高,通过WAL技术来避免。WAL技术关键点就是先写日志,后写磁盘,也就是先写记账板,后写账本。
流程:
1.不繁忙情况: 有一条语句需要更新,innodb引擎先记录到redo log中,更新内存,这个时候就算更新完成了。在不繁忙的时候再读入磁盘
2.繁忙情况下:记账板写满,把数据更新到记账本,擦掉记账板。
redo log有个好处,可以再数据库发生异常重启保证之前提交的数据不丢失,这个能力成为crash-safe
binlog日志:
特性:server层日志,归档日志,记录数据库执行的查询、DML、DDL语句,记录内容是追加写,可以生成多个文件。
redo log 和 binlog 不同:
1、redo log 是innodb引擎特有的,基于innodb引擎层面的日志。 而binlog是server层日志,所有引擎都可以使用。
2、redo log 是物理日志,记录了做了什么操作。而binlog日志是逻辑日志,具体记录了操作语句。
3、redo log 循环写,空间固定会用完。而binlog是可以追加写入生成多个文件的,不会覆盖以前日志。
执行器和innodb引擎执行update语句流程: update t set c=c+1
1、执行器先找引擎拿到ID=2这一行数据。数据在内存直接返回,不在的话先从磁盘读入内存然后返回。
2、执行器拿到引擎给的数据,将c值+1,得到新数据后调用引擎接口写入这条新数据
3、引擎将这条新数据更新到内存中(change buffer),同时将这条更新操作记录到redo log 里边,此时redo log处于prepare状态。然后通知执行器执行完成了,随时可以提交
4、执行器生成这个操作记录的binlog,并把binlog写入磁盘。
5、执行器调用引擎的提交事务接口,引擎把刚刚写入的redo log状态改成commit状态,更新完成。
图中浅色框表示是在 InnoDB 内部执行的,深色框表示是在执行器中执行的: