Ⅰ, 事务的实现
这里我们先抛出答案, 通过答案再展开分析
特性 | 实现 |
---|---|
A(原子性) | redo |
C(一致性) | undo |
I(隔离性) | lock |
D(持久性) | redo/undo |
本节针对 redo 展开分析
Ⅱ,redo 详解
2.1 redo log buffer
redo 就是我们常说的重做日志, 用来实现持久性
MySQL 目录下两个 ib_logfile 文件, 就是重做日志文件, 在 ssd 场景下至少设置为 4G
redo log 里面记录的是每个 page 修改操作的物理逻辑日志(不是完全的二进制的差异值, 比如一个 sql 修改了一千万行, 一千万个 page 被修改了, 那记录的是 1000w page 的变化, 而不是 sql 语句)
redo 由 redo log buffer 和 redo log file 组成, 重做日志先写入一块内存, 再定期刷新到磁盘
先看下 redo log buffer
它由很多个 log block 组成, 每个 log block 512 个字节, 不需要 doublewrite
innodb_log_buffer_size 8M 即可, 不需要太大, 一秒钟写满 8M 不太可能
redo log 刷盘的条件
1master thread 每秒从内存刷到磁盘
5.6 版本后, 增加 innodb_flush_log_at_timeout 参数, 可以设置刷新间隔, 默认为 1, 调大一点可减少 io, 提升性能, 但不建议
2redo log buffer 使用大于 1/2 也会刷
3事务提交时进行刷新, 即使上面两个条件不满足(事务持久性的要求)
innodb_flush_log_at_trx_commit={0|1|2}, 默认为 1, 事务提交时将 redo log buffer 写到磁盘(即使上面两个条件不满足, 这样 crash 了就还可以通过 redo 恢复), 只有是 1 的时候 innodb 才能真正达到持久性的标准
事务对 page 做了修改, 提交的时候并不需要保证赃页刷到磁盘, 只需要保证将对应修改的日志刷过去就可以了
0 表示交给 master thread 每秒刷新, 事务提交不将 redo log buffer 刷到磁盘, 最多会丢失 1s 的事务
2 表示事务提交时仅将 redo log buffer 写到操作系统缓存, 所以 MySQL 重启, 只要操作系统没重启, 那数据还是在的额
2.2 redo log file
先弄个图看看 redo buffer 刷盘吧
每个 ib_logfile 都分为很多个 512bits 的块, 最前头 2k 是留出来写 checkpoint 的, 通过对比两个 cp 可知哪个是最新的, cp1 和 cp2 轮询写确保 cp 不会坏掉, 一个坏了也没事, 即使用小的 cp 顶多就是恢复的时候多一点时间, 没有 oracle 的归档
优点: 这样做的好处是不需要归档, 少了 IO 操作
缺点: 如果 redo_log_file 太小则可能需要等待, 因为当要覆盖 log_file 中的 log_block 时, 如果该 log_block 中的脏页还没有进行刷新的话, 则需要等待这个脏页进行刷新
所以需要把 redo log file 设置的尽可能的大
redo 日志分类
物理日志: 记录整个 page 的变化(diff)
逻辑日志: Like SQL 语句
物理逻辑日志: 根据 page 进行记录, 内容逻辑
redo log file 与 redo log buffer 内容一致
- +---------------+----------+---------+---------------+
- | redo_log_type | space no | page no | redo log body |
- +---------------+----------+---------+---------------+
- # redo log 类型 表空间号 页号 redo log 内容
- MLOG_REC_INSERT
- +------+--------+------+---------+------------+-------+---------+-----------+----------+
- | type | space | page | cur_rec | len & | info | origin | mis_match | rec body |
- | | no | no | _offset | extra_info | _bits | _offset | _index | |
- +------+--------+------+---------+------------+-------+---------+-----------+----------+
- MLOG_REC_DELETE
- +------+----------+---------+--------+
- | type | space no | page no | offset |
- +------+----------+---------+--------+
rec body 根据 page 的变化来记录, 而不是根据操作 SQL 来记录, 所以偏物理日志
因为还记录了 redo log body, 一个具体操作, 所以又叫逻辑
每种不同类型的 redo log 的内在格式可能长得不一样
相关参数
innodb_log_file_size 单个 redo 文件大小(推荐 8G, 官方推荐等于 bp)
之前不建议调大因为有 bug, 如果调大, 恢复速度会很慢 O(N^2)
5.5 版本的 redo 文件总大小 (num * size) 最大只能 4G
5.6 之后限制未 512G, 调大后唯一的问题就是恢复的内容变多了
5.6 之后, 正常关闭 MySQL, 然后调整该值, 会自动调整文件大小
innodb_log_files_in_group
innodb_log_group_home_dir 和数据文件分开, 选择更快的磁盘
来源: http://www.bubuko.com/infodetail-2912430.html