MYSQL45讲-第二讲-一条SQL更新语句是如何执行的
一条更新SQL在执行时
1.首先会判断待更新的数据是否在内存中,如果是在内存中则直接更新内存的数据,否则将数据读入内存再更新。(WAL:write aHead logging)
2.将更新操作写入redo log,进入prepare状态。
3.写入binlog。
4.提交commit。
5.定时或redo log满了后将redo log写入磁盘。
1. 为什么要有redo log?
- redo log会将每次更新的操作记录下来,待系统比较空闲的时候再将redo log写入磁盘,从而避免每一次的更新操作都要写入磁盘,耗费IO资源。
- 有了redo log之后,数据库异常重启之后,即使没及时更新到磁盘,数据也能在redo log上找回。这个能力称为crash-safe。
- 综上,redo log保证了事务的持久性。
2. binlog是什么?
binlog是mysql自带的日志系统,一般用于归档。
3. redo log 和 binlog 的区别是什么?为什么要有两份日志?
- binlog是mysql自带的日志系统,记录的是逻辑更新,有两种模式,一种是记录sql,一种是记录行的内容。redo log是innodb独有的日志系统,记录的是物理更新,记录的是这个行在这个页里做了什么更新。(逻辑日志可以给别的数据库使用,物理日志只有自己能用,Crash-safe是崩溃恢复,就是原地满血复活;binlog恢复是制造一个影分身(副本)出来)
- binlog采用的追加写,不用覆盖原有的内容,内存会越来越大。而redo log有固定的内存大小,写满后会将之前一部分写入磁盘,然后覆盖之前的那部分。
- binlog由于完整的特点,可以将数据库恢复到任意时刻,例如我想讲数据库恢复到昨天晚上,只需要找到里最晚最近的备库,然后按照备用数据库的产生时间到昨晚之间的binlog恢复即可,redo log因为不完整不具备这种能力。
- redo log的作用是WAL和crash-safe,binlog是不知道从哪条记录开始是未刷到磁盘的。
4.为什么要有两阶段提交?
- 两阶段提交的目的是确保两份日志的一致性。
- 如果更新完redo log提交后系统宕机,在恢复后可以根据redo log获得正确的操作,但是因为在binlog中没有,以后根据binlog恢复数据库的时候就会漏掉这一条数据。
- 如果先更新binlog后系统宕机,那么系统恢复后由于redo log没有这个记录所以内存中和磁盘里都不会有,但是在以后根据binlog恢复数据库的时候就会凭空出现这条记录。
- 在两阶段提交下,binlog写失败redo log会回滚,保证一致性。
- 实际上prepare+binlog写成功就可以进行数据恢复了,还需要commit的原因是因为在恢复的时候可以根据已经commit的数据恢复,未commit的数据再去binlog里找,找到了再commit,而不是全部去binlog里找,太耗时。