mysql的binlog/undolog/redolog
(1)redo log(重做日志)
在 MySQL 里,如果每一次的更新操作都需要写进磁盘,然后磁盘也要找到对应的那条记录,然后再更新,整个过程 IO 成本、查找成本都很高。MySQL里使用 WAL 技术,WAL 的全称是 Write-Ahead Logging,它的关键点就是先写日志,再写磁盘。具体来说,当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到 redo log里面,并更新内存,这个时候更新就算完成了。同时,InnoDB 引擎会在适当的时候,将这个操作记录更新到磁盘里面,而这个更新往往是在系统比较空闲的时候做。InnoDB 的 redo log 是固定大小的,比如可以配置为一组 4 个文件,每个文件的大小是 1GB,那么总共就可以记录 4GB 的操作。从头开始写,写到末尾就又回到开头循环写。有了 redo log,InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为crash-safe。作用:确保事务的持久性。防止在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的持久性这一特性。
(2)undo log(回滚日志)
undo log是回滚日志,提供回滚操作。作用:保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读
(3)bin log(归档日志)
binlog是属于MySQL Server层面的,又称为归档日志,属于逻辑日志,是以二进制的形式记录的是这个语句的原始逻辑,依靠binlog是没有crash-safe能力的.作用:用于复制,在主从复制中,从库利用主库上的binlog进行重播,实现主从同步。用于数据库的基于时间点的还原。
(4)redo log和binlog区别
- redo log是属于innoDB层面,binlog属于MySQL Server层面的,这样在数据库用别的存储引擎时可以达到一致性的要求。- redo log是物理日志,记录该数据页更新的内容;binlog是逻辑日志,记录的是这个更新语句的原始逻辑- redo log是循环写,日志空间大小固定;binlog是追加写,是指一份写到一定大小的时候会更换下一个文件,不会覆盖。- binlog可以作为恢复数据使用,主从复制搭建,redo log作为异常宕机或者介质故障后的数据恢复使用。
(5)一条update语句执行的全部流程分析
update T set c=c+1 where ID=2;
步骤分析:
1.在执行这条更新语句时,会先从数据缓存页中(即data buffer pool)中查看是否有该条数据(查看的是LRU List这个双向链表的描述缓存页信息、如果不存在,即从磁盘中加载读取,然后加载进buffer pool中,执行器对该条语句进行更新之后,buffer pool中的FlushList会存放被修改的脏数据页的描述信息。)2.引擎将这行新数据更新到内存中,同时将这个更新操作记录到 redo log 里面.首先引擎会进行书写undo log,undo日志用于记录事务开始前的状态,用于事务失败时的回滚操作;redo日志记录事务执行后的状态,用来恢复未写入data file的已成功事务更新的数据。例如该条sql语句的事务序号为T1,其对数据c进行修改,设c的原值是5,修改后的值为+1变成了6,那么Undo日志为,Redo日志为。此时 redo log 处于 prepare 状态。uodo log和 redo log都是写到log buffer中的,根据mysql的配置,innodb_flush_log_at_trx_commit的值(该值的配置下面做以说明),则将redo日志写到log file,并刷新落盘。然后告知执行器执行完成了,随时可以提交事务。3.执行器生成这个操作的 binlog,并把 binlog 写入磁盘。4.执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成。(即两阶段提交)
buffer pool中的缓存图
(6)innodb_flush_log_at_trx_commit:参数解析
命令为》 show variables like "innodb_flush_log_at_trx_commit";0: 由mysql的main_thread每秒将存储引擎log buffer中的redo日志写入到log file,并调用文件系统的sync操作,将日志刷新到磁盘。1:每次事务提交时,将存储引擎log buffer中的redo日志写入到log file,并调用文件系统的sync操作,将日志刷新到磁盘。2:每次事务提交时,将存储引擎log buffer中的redo日志写入到log file,并由存储引擎的main_thread 每秒将日志刷新到磁盘。
(7) sync_binlog :参数解析
命令为》show variables like "sync_binlog";0 :存储引擎不进行binlog的刷新到磁盘,而由操作系统的文件系统控制缓存刷新。1:每提交一次事务,存储引擎调用文件系统的sync操作进行一次缓存的刷新,这种方式最安全,但性能较低。n:当提交的日志组=n时,存储引擎调用文件系统的sync操作进行一次缓存的刷新。
(8)mysql宕机时机的场景分析
mysql的日志是在一些场景下使用,平时只起到记录的作用,用在宕机、恢复到某一时态,或者主从使用:1.如果redolog写入了,处于prepare状态,binlog还没写入,那么宕机重启后,redolog中的这个事务就直接回滚了。2. 如果redolog写入了,binlog也写入了,但redolog还没有更新为commit状态,那么宕机重启以后,mysql会去检查对应事务在binlog中是否完整。如果是,就提交事务;如果不是,就回滚事务。(redolog处于prepare状态,binlog完整启动时就提交事务,为啥要这么设计? 主要是因为binlog写入了,那么就会被从库或者用这个binlog恢复出来的库使用,为了数据一致性就采用了这个策略)redo log和binlog是通过xid这个字段关联起来的。