日志系统:一条SQL更新语句是如何执行的?
一、更新语句执行流程
- MySQL可以恢复到半个月内任意一秒的状态。如何做到?
- 更新语句同样会把查询语句流程走一遍。
- 连接器连接客户端—>在一个表上有更新的时候,跟这个表有关的查询缓存会失效(不建议使用查询缓存)—>分析器根据语法分析得知是更新语句–>优化器决定执行索引—>执行器负责执行找到这一行后更新。
- 更新流程还涉及到redo log(重做日志)和 binlog(归档日志)。
二、redo log(重做日志)
- 属于引擎层,InnoDB特有的日志。
- 物理日志,记录在某个数据页上做了什么修改。
- 循环写。
- WAL技术:是先写日志,再写磁盘。
- InnoDB引擎先把更新记录写到redo log中,更新内存,选择合适(系统空闲)的时间将操作记录更新到磁盘。如果redo log满,将一部分内容写到磁盘中。
- redo log固定大小
- InnoDB可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为crash-safe。
三、binlog(归档日志)
- Server层的日志。
- 逻辑日志,记录的 是这个语句的原始逻辑。
- 追加写,不会覆盖以前文件。
mysql> update T set c=c+1 where ID=2;
浅色框表示是在InnoDB内部执行的,深色框表 示是在执行器中执行的mysql> update T set c=c+1 where ID=2;
浅色框表示是在InnoDB内部执行的,深色框表 示是在执行器中执行的。- 数据恢复:首先,找到最近的一次全量备份,如果你运气好,可能就是昨天晚上的一个备份,从这个备 份恢复到临时库; 然后,从备份的时间点开始,将备份的binlog依次取出来,重放到中午误删表之前的那个时刻
- 采用两阶段提交解决数据库的状态和用它的日志恢复出来的库的状态不一致问题。
四、小结
- redo log用于保证crash-safe能力。innodb_flush_log_at_trx_commit这个参数设置成1的时候, 表示每次事务的redo log都直接持久化到磁盘。
sync_binlog这个参数设置成1的时候,表示每次事务的binlog都持久化到磁盘。