在上一篇中我们说到了mysql的基础架构,通常一个查询操作只会涉及到基础架构中的那几部分;
首先连接数据库,分析器进行语义、语法分析,优化器生成执行计划和索引选择、执行器执行对应的语句、存储引擎查看内存中是否有对应的数据,有的话直接返回,没有的话从磁盘查找(不考虑查询缓存);但是对于更新操作的话还需要用到日志来辅助
日志的作用:1、数据恢复需要用到binlog
2、数据库重启后需要redo log来保证数据的可靠,会出现数据还没写入磁盘服务器异常重启的情况
一、redo log(重做log)
由于直接更新磁盘响应较慢,所以引入了redo log,除了解决这个问题外它还能保证crash-safe
redo log 是InnoDB特有的,他可以保证crash-safe(即数据库发生异常重启,之前提交的数据都不会丢失),因为提交记录都被保存在redo log中,重启之后仍然会将redo log中的提交记录刷新到磁盘
redo log大小是固定的,更新操作时并不会先直接更新磁盘中的数据,而是先将更新操作记录在redo log中,然后再更新内存中的数据,当数据库空闲时再将redo log中的记录刷新到数据库,如果数据库一直不空闲当redo log日志满了后数据库会先暂停其他的操作,先将redo log中的记录刷新到磁盘,这时会出现查询缓慢的情况(sql抖动)
二、binlog(归档日志)
binlog时mysql自带的,作用于service层,binlog的大小是可设置的,他的大小跟数据备份的周期相关,因为数据恢复需要用到上一次的数据库备份与备份时间到误操作前时间的binlog,除了数据恢复外扩容也需要用到binlog日志
Binlog有两种模式,statement 模式的话是记sql语句, row模式会记录行的内容,记两条,更新前和更新后都有
两者的不同:
一、redo log是InnoDB特有的 binlog是mysql自带的,任何存储引擎都可以使用
二、redo log记录的是修改操作,binlog记录的是逻辑
三、数据库会自动对redo log做处理,会将里面的记录同步到磁盘,而binlog不会被自动处理
为了保证redo log和binlog的数据一致采用了两阶段提交,两阶段提交的流程:
用update table1 set c=c 1 where id =1来看
1、执行器先请求存储引擎id=1的c字段的值,如果内存中存在c的值则直接返回,否则存储引擎会去读磁盘
2、执行器将age的值加1,请求存储引擎将设置c的值
3、存储引擎将该操作记录到redo log 文件中,将redo log的状态设置为prepare状态,然后告知执行器施行完成
4、执行器收到消息后将该操作写入binlog日志中,并将binlog写入磁盘
5、执行器调用存储引擎的提交事务接口,存储引擎将redo log的状态设置为commit状态,更新完成
深色为执行器的操作,浅色为存储引擎的操作
一些问题:
一、为什么需要保证两个日志的一致性
因为如果两个日志不一致的话只能说明某些操作被误记录或者没被记录,那数据恢复时数据肯定就会有问题,数据库扩容也会有问题。
需要考虑的问题,本篇只解释了部分问题
1. redo log为什么会存在.
3. redo log 为什么可以保证crash safe机制.
4. binlog的概念是什么, 起到什么作用, 可以做crash safe吗?
5. binlog和redolog的不同点有哪些?
7. 执行器和innoDB在执行update语句时候的流程是什么样的?
8. 如果数据库误操作, 如何执行数据恢复?
9. 什么是两阶段提交, 为什么需要两阶段提交, 两阶段提交怎么保证数据库中两份日志间的逻辑一致性(什么叫逻辑一致性)?
10. 如果不是两阶段提交, 先写redo log和先写bin log两种情况各会遇到什么问题?