mysql中的日志文件类型
- redo log 重做日志
- undo log 回滚日志
- bin log 二进制日志
- slow log 面查询日志
- error log 错误日志
- relay log 中继日志
mysql 修改数据过程
将数据从磁盘 --> buffer pool -->修改buffer pool数据 --> redo log buffer --> redo log
redo log
为什么要引入redo log
mysql对数据做修改操作的时候,需要把
数据页从磁盘读取到buffer pool中,然后在buffer pool中修改,此时buffer pool中的数据与磁盘上的数据不一致,这是buffer pool中的数据页为dirty page脏页。如果此时 发生数据库的非正常重启,这部分修改的数据还在内存中,并没有持久化到磁盘,就会导致数据丢失,于是就引入了redo log,当buffer pool中的数据发生变更的时候,把相应的修改记录到redo log,当发生非正常启动的时候,可以根据此文件的记录,将修改重新应用到磁盘文件,保持数据一致。
- 同步到磁盘文件是随机IO没效率低下。
- 同步到redo log中是顺序IO,效率高效。
redo log 简介
redo log 包含内存的日志缓冲
redo log buffer和 磁盘的redo log file文件 redo log 用于记录事务变的日志,是InnoDB 存储引擎级别的日志
redo log 存在形式
- redo log文件是固定大小。并且以文件环的方式循环写入,ib_logfile0 -> ib_logfile1 -ib_logfile2 ->ib_logfile0 \
- redo log file大小设置的越大,恢复的时间越长;设置的越小会导致频繁的切换redo log file,随机io
持久化方式
在开启事务的时候就会产生redo log,但不是立即写入到redo log 文件中,而是先写入到redo log buffer中(redo log buffer中未刷新到磁盘日志文件的称之为脏日志) ;buffer pool中的未刷写到磁盘的数据页为 dirty page ·脏页
脏日志的持久化- mysql mster线程周期性任务:每一秒一次(包含尚未提交的事务【这里就是为了两阶段用】)
- mysql mster线程周期性任务:每十秒一次
- redo log buffer size:缓冲区剩余空间小于1/2
- redo log file: 总大小(innodb_log_file_size*innodb_log_files_in_group)即将达到阈值
脏页的持久化,(刷盘规则:检查点(checkpoint))- sharp checkpoint: 恢复重做时
- fuzzy checkpoint:一次只刷新部分日志到磁盘
- master thread checkpoint:mster线程周期性任务,每秒/十,秒刷写一定比例
- flush_lru_list checkpoint: buffer pool lru 触发
- asyn/sync flush checkpoint: 脏页同步刷盘/异步刷盘
- dirty page too much checkpoint:脏页的比例由(innodb_max_dirty_pages+pct),默认超过75%,就强制刷写一部分。
- mysql 停止时,
脏页和脏日志的刷入磁盘(innodb_fast_shutdown)控制,默认值为1- 0:
脏页和脏日志都刷新到磁盘 - 1:
脏页刷新到磁盘 - 2:
脏日志刷新到磁盘
- 0:
redo log 相关参数
- innodb_log_file_size 每个redo log 文件大小,默认5M
- innodb_log_files_in_group redo log文件的个数。默认2个,最大100个。
- innodb_log_file_group_home_dir 文件存放路径
- innodb_log_buffer_size 缓冲区大小,默认8M,可设置1-8M。
- innodb_flush_log_at_trx_commit
redo log buffer刷新到磁盘的时机 0|1|2- 0 由master线程周期性任务刷新。
- 1 在事务commit的时候,fsync 写入磁盘文件。
- 2 在事务commit的时候,将
redo log buffer写入到文件系统缓存(file system buffer),由文件系统内部来fsync到磁盘文件。如果数据库实例crash,不会丢失redo log,如果服务器crash,文件系统来不及fsync到磁盘,会丢失这一部分。
undo log
在数据修改的时候,不仅记录了redo log,还记录了对应的undo log,undo log记录的是 逻辑日志,二redo log记录的是物理日志。undo log 针对一条修改语句会记录一条相反的逻辑语句
为什么要记录undo log
记录事务开始前的状态,用于事务失败时的回滚操作及提供多版本并发控制(MVCC)下的
非锁定读,undo log 也会产生 redo log,undo log的语句也要实现持久化性。
undo log的删除
事务提交的时候,innodb 不会立即删除undo log,因为后续还有可能用到undo log,当隔离级别的RR时,事务读取的都是开启事务的最新提交的版本,只要该事务不结束,该版本就不能删除。在事务提交的时候,会将该事务对应的undo log 放入删除列表中,之后通过
purge线程来删除
delete: 不会直接删除,而是先将delete flag 标记,之后由purge 线程完成删除。 update: - 更新键为主键:先删除新记录,再插入原记录 - 更新键为非主键:在undo log中反向记录update 命令
存在形式
innodb对于undo log的管理采用分段的方式。rollback segment 称之为
回滚段,每个回滚段中包含1024个 undo log segment。默认支持128个 回滚段,即支持128*1024个undo 的操作,通过innodb_rollback_segments自定义回滚段的数量
相关参数
- innodb_max_undo_log_size:启用了独立空间才会生效,超出大小后,purge线程根据次参数和innodb_max_undo_log_size及innodb_purge_rseg_truncate_frequency进行文件切分,切分后每个10M。
- innodb_undo_log_truncate:
- innodb_purge_rseg_truncate_frequency:控制purge 回滚段的频度,默认128;
- innodb_rollback_segments: 控制purge 回滚段的数量,默认128;
- innodb_undo_tablespaces: 为undo log 设置独立的表空间个数。默认0,不开启独立表空间。
当数据库写压力大时,可以设置独立undo 表空间,把undo log从 .ibdata文件中分离出来,指定 undo_directory目录到更高效的存储介质上,加快undo log的读写性能
binlog
mysql 服务级别的二进制之日,用于数据恢复和主从复制。
binlog和redo log的区别
- bin log 是mysql server的,redo log是innodb引擎的
- bin log 是事务提交后一次性写入多条sql语句,redo log是在事务开始(prepare)后就逐条写入
bin log的记录格式
- row 记录每行数据的实际变更字段,日志文件大,准确性强
- statement 记录sql语句,日志文件小,准确性差
- mixed 上面两种模式的混合 文件大小适中,准确性适中
相关命令
show bin log events in xxx.001 查看bin log 文件内容 show binary logs #获取bin log 文件列表 mysqlbinlog 命令工具
redo log和binlog的两阶段提交
mysql 通过2pc来完成事务的一致性,即redo log和bin log的一致性。redo log在事务执行的过程中逐条语句记录日志 prepare -> sql1 -> sql2 -> sql3 -> 记录bin log commit 也正是因为记录redolog 的2pc状态和binlog 还要用作同步到从库,所以要先记录redo log 再记录bin log
1、先写binlog、后写redolog
· binlog 写失败 无影响
· binlog 写成功、redolog 写成功 无影响
· binlog 写成功、redolog 写失败,master中无,slave从binlog中同步了
2、先写redolog、后写binlog
· redolog 写失败 无影响
· redolog 写成功、binlog写成功 无影响
· redolog 写成功、binlog写失败,master中有,slave中无
基于1、2来看无论先写那个都有问题,所以就出现了两阶段提交,先写redolg再写binlog,并且将写redolog 拆分为两阶段
· 写redolog-prepare 失败终止,无影响
· 写binlog 失败,失败后server通过redolog恢复,因为是prepare,再看binlog是否存在,如果不存在则不处理,如果存在则进行恢复,所以无影响
· 写redolog-commit,修改redolog的状态,失败,因为是prepare,再看binlog是否存在,如果不存在则不处理,如果存在则进行恢复,所以无影响