15 日志和索引相关问题
1.在两阶段提交的不同瞬间,mysql如果发生异常重启,是怎样保证数据完整性的。
如果在图中A的地方,也就是写入redo log处于prepare阶段之后,写binlog之前,发生了崩溃(crash),由于此时binlog还没写,redolog还没提交,所以崩溃恢复的时候。事务会回滚,这时,binlog还没写,所以不会传到备库。
时刻B,binlog写完,redo log还没commit前发生crash,崩溃恢复的mysql处理
1.如果redo log里面是事务是完整的,也就是已经有了commit标识,则直接提交
2.如果redo log里面的事务只有完整的prepare,则判断对应的事务binlog是否存在并完整
A.如果是,则提交事务
B.否则,回滚事务
时刻B发生crash对应的就是2(a)的情况,崩溃恢复过程事务会被提交。
Q2.mysql怎么知道binlog是完整的
一个事务的binlog是有完整格式的
Statement格式的binlog,最后会有COMMIT
Row格式的binlog,最后会有一个XID event
在5.6.2之后,还引入了binlog-checksum参数来验证binlog内容的正确性
Q3:redo log和binlog是怎么关联起来的
因为他们都有一个共同的数据字段,叫XID,崩溃恢复的时候,会按顺序扫描redo log;
如果碰到既有prepare,又有commit的redo log,就直接提交
如果碰到只有prepare,而没有commit的redo log,则拿着XID去binlog找对应的事务
Q4:处于prepare阶段的redo log加上完整binlog,重启就能恢复,mysql为什么这样设计
为了保证主库和备库的数据一致性
Q8:redo log一般设置多大
Redo log设置太小的话,会导致很快就写满,然后不得不强行刷redo log,这样WAL机制的能力就发挥不出来了
所以,如果现在常见的几TB的磁盘,直接将redo log设置为4个文件,每个文件1GB。
Q9:正常运行的实例,数据写入后的最终落盘,是从redo log更新过来的还是从buffer pool更新过来的。
实际上,redo log并没有记录数据页的完整数据,所以并没有能力自己更新磁盘数据页
1.如果正常运行的实例,数据页被修改后,跟磁盘的数据页不一致,称为脏页,最终数据落盘,就是把内存中的数据页写盘,这个过程与redo log 无关。
2.在崩溃恢复的情况下,InnoDB如果判断到一个数据页可能在崩溃恢复的时候丢失了更新,就会将他读到内存,然后让redo log更新内存内容,更新完成后,内存页变成脏页,回到第一种情况。
Q10:redo log buffer是什么,是先修改内存,还是先写redo log文件
Redo log buffer就是一块内存,用来先存redo日志的,也就是,在执行第一个insert的时候,数据的内存就被修改了,redo log buffer也写入了内存中。
真正把日志写到redo log文件,是在执行commit语句的时候做的。