REDO日志内容
REDO日志是物理逻辑日志,根据页进行记录,记录的内容是逻辑的(页的变化,并非SQL语句)
+---------------+----------+---------+---------------+
| redo_log_type| space no | page no | redo logbody |
+---------------+----------+---------+---------------+
redo log 类型 表空间号 页号 redo log 内容
相关参数
REDO 即常说的重做日志,用来实现持久性,相关组件有有 redo log buffer 和 redo log file 。
- --innodb_log_buffer_size <-- 通常 8M 已经足够使用
- --innodb_log_file_size <-- 单个 innodb redo文件的大小(推荐8G,官方建议等于 buffer_pool_size)
- --innodb_log_files_in_group <-- 设置有几个 redo 日志文件
- --innodb_log_group_home_dir <-- 可以外考虑将 redo 文件和数据文件分开,放在更快的盘
5.5版本的redo文件的总大小是有限制的(小于4G),5.6以后限制为512G,如果调的太大,恢复速度会很慢。
redo日志循环写的好处是不需要归档,减少了IO操作;缺点是如果 redo_log_file 太小,则可能需要等待(所以需要把 redo log file 设置的尽可能的大)。
redo log buffer 和 redo log 都是由 log block 组成,每个 log block 512 字节。
修改日志数量和大小
1.检查innodb_fast_shutdown的值
该参数可取0,1,2三个值,0表示shutdow normal,1表示shutdown immediate(默认),2表示shutdown abort。如果该值为2,先修改为1。
2.正常关闭mysql后调整参数
MySQL 5.6以后调整完参数即可直接启动数据库,MySQL会自动扩展/减小该文件大小;之前的版本需要先将原日志文件移走后再启动数据库。
REDO Log Buffer的刷新条件
- master thread 每秒刷新 buffer 到 logfile。5.6 版本后,增加 innodb_flush_log_at_timeout 参数(默认为1),可以设置刷新间隔,该值设置的越大,相对性能就好一点(IO 操作变少),但是如果 innnodb_flush_log_at_trx_commit 的值不是1,并且发生宕机,丢失的数据也就越多。
- redo log buffer 使用量大于1/2 时进行刷新。
事物提交时进行刷新(--innnodb_flush_log_at_trx_commit = {0|1|2})
innnodb_flush_log_at_trx_commit
- 0 - 事物提交的时候并不把日志(redo log buffer)写入到磁盘(1s 或者 大于1/2 时刷日志)
- 1 - 事物每次提交的时候要确保日志(redo log buffer)写入磁盘,即使宕机,也可以通过redo恢复,达到持久性的要求
- 2 - 事物提交的时候,仅将日志(redo log buffer)写入到操作系统缓存
1 可以保证数据不丢失,建议设置为1。
0 可能会丢失1秒(innodb_flush_log_at_timeout)的数据,
2 如果是mysql停止,不会丢数据,因为在缓存里面,但是当系统宕机了,在缓存里面的数据就丢失了。
redo 刷新情况
mysql> show engine innodb statusG
Log sequence number 537665207 -- 当前内存中的LSN
Log flushed up to 537665207
Pages flushed up to 537665207 -- 最后刷新到磁盘的页上的最新的LSN
Last checkpoint at 537665198
-- 两者之差表示 redo log 还有多少没有刷新的磁盘
-- 如果该差值接近重做日志的总大小的75%时,表明你的 innodb_log_file_size 设置小了(75%左右就强制刷新了)
组提交
一次 fsync 刷新多个事务,性能提高10倍左右,5.6 默认开启,不能关闭。5.5 有 bug,开启 binlog 后组提交失效,性能较差。
fsync
- O_DIRECT 仅对写数据时有用,redo 日志是不会通过 O_DIRECT 方式写入到磁盘的,而是写到文件系统的缓存中
- fsync 可以将 redo 日志从内存中直接同步到磁盘
- O_DIRECT 仅仅写数据到磁盘,但是数据的元数据没有同步,比如time、owner、size等等,从数据的角度看,fsync可以将元数据同步到磁盘
IOPS--决定-->fsync--决定-->TPS。
假设HDD磁盘IOPS为100(即每秒只有100次fsync),且一个事务中只有一条 insert into 的SQL时,那1秒钟内就只能插入100条数据,即TPS就只有100。
假设使用组提交 ,一次 fsync 可以刷新5个事务(假设),那在IOPS为100的情况下,也可以提交500个事务,这样性能就得到了提升(一次IO提交多个事物)。