MySQL数据库——查询语句和更新语句怎么执行
一条SQL查询语句的执行:连接器(连接数据库)、查询缓存(在数据更新的时候会降低效率,已经不用了)、分析器(做什么)、优化器(怎么做更好)、执行器。
慢查询日志有一个rows_examined字段,表示这个语句在执行过程中扫描了多少行,这个值即使在执行器每次调用引擎获取数据行的时候累加的。
上述都属于server层,还有存储引擎层,是负责存储数据,提供读写接口。
一条SQL更新语句的执行:连接器、分析器(知道是更新语句)、优化器(知道ID索引)、执行器(找到行更新)
此外,更新流程还涉及两个重要的日志模块:redo log重做日志、bin log归档日志。
(1)物理日志redo log:如果有人要赊账,老板要有黑板和账本一起配合才能加快效率。
如果只有账本,人家要赊账,就要找到账本记录,计算,再写结果,卖的时候很麻烦。还是先在黑板写比较方便。
黑板和账本的配合就是WAL,即write-ahead-logging技术,就是先写日志,再写磁盘。
需要更新的时候,InnoDB引擎就先把记录写到redo log(黑板)上,并更新内存(大脑意念),这个时候更新完成。然后InnoDB引擎在适当的空闲的时候将操作记录更新到磁盘里面(账本)。
redo log是固定大小的,就像黑板写满了,老板就要放下手中的活,更新账本,擦掉黑板,腾出空间。
write pos是当前记录的位置,checkpoint是当前擦除的位置。二者之间是黑板空着的位置,记录操作,如果write pos追上checkpoint,说明黑板满了,这时候不能执行更新,得停下来擦掉记录,推进checkpoint。
有了redo log,InnoDB就可以保证即使数据库发生异常重启,之前提交得记录都不会丢失,这个能力叫做crash-safe。
比如老板忘记记录,但是黑板有,停业几天依旧可以记录。
redo log用于保证crash-safe的能力。innodb_flush_log_at_trx_commit这个参数设置成1的时候,表示每次事务的redo log都直接持久化到磁盘,这样可以保证MySQL异常重启之后数据不丢失。
(2)逻辑日志binlog:(最开始没有InnoDB引擎,只实现binlog无法实现crash-safe功能)
redo log是InnoDB引擎特有的日志,而server层也有自己的日志,叫做binlog即归档日志。
redo log是物理日志,记录在某个数据页做什么修改;bin log是逻辑日志,记录这个语句的原始逻辑。
redo log是循环写的,空间固定会用完;bin log是可以追加写入的,不会覆盖以前的日志。
redo log的写入分成两个步骤:prepare和commit,这就是两阶段提交。为了让两份日志之间的逻辑保持一致。(反证法)
binlog有sync_binlog参数,设置成1的时候,表示每次事务的binlog都持久化到磁盘,可以保证MySQL异常重启之后binlog不丢失。