MySQL的redo与undo日志

redo日志

MySQL运行时,会把数据从硬盘加载到内存中,如果每次执行一次事务都做一个落盘的操作,这样做保证了一定的安全,但是会降低性能,磁盘的IO可能会很大。
所以就有了这样一个机制,当用户修改数据的时候,MySQL从硬盘加载数据到内存进行更改,当用户commit的时候,数据不直接写入到硬盘,而是把这个改变的信息写到redo日志中,这时候redo日志是在内存中的,同样还是需要写到硬盘,但是这个IO是顺序IO而且数据量更小。

redo日志文件

-rw-r-----. 1 mysql mysql  48M Jan 18 00:51 ib_logfile0
-rw-r-----. 1 mysql mysql  48M Nov  4 09:46 ib_logfile1 

redo日志文件的大小

innodb_log_file_size         

指定重做日志文件组中文件的数量

innodb_log_files_in_group    

指定日志文件组所在的路径

innodb_log_group_home_dir 

刷写redo日志频率

innodb_flush_log_at_trx_commit = 1/0/2
# 0:redo buffer 每秒钟,向redolog文件中刷新一次数据  ---性能最好
# 1:redo buffer 每次事务提交,向redo log文件中刷新一次数据---安全最高
# 2:redo buffer 每次事务提交,向OS buffer中刷新一次数据,但每秒钟向redo log文件中刷新一次数据---折中

innodb数据文件及redo log的打开、刷写模式

innodb_flush_method
#有三个值:fdatasync(默认),O_DSYNC,O_DIRECT
#默认是fdatasync,调用fsync()去刷数据文件与redo log的buffer
#为O_DSYNC时,innodb会使用O_SYNC方式打开和刷写redo log,使用fsync()刷写数据文件
#为O_DIRECT时,innodb使用O_DIRECT打开数据文件,使用fsync()刷写数据文件跟redo log!

最安全的设置:

innodb_flush_log_at_trx_commit = 1 
Innodb_flush_method = O_DIRECT

性能最高的:

innodb_flush_log_at_trx_commit = 0 
Innodb_flush_method = fdatasync

折中:

innodb_flush_log_at_trx_commit = 2
Innodb_flush_method = O_DSYNC

LSN

LSN(Log Sequence Number)日志序列号,举个例子,用户从硬盘加载数据到内存,假设这个数据的LSN为101,这时候对这个数据进行修改,redo日志就回把这条修改的记录LSN设置为102,这样当数据库宕了,重启数据库的时候,它自己会对比数据是否一直,比如redo日志LSN到了101,但是数据文件里面LSN才到100这个数据库就会认为数据不一致,就会从redo日志吧执行过的操作再重放一遍。保证了数据的安全。

undo日志

现在有个事务执行,对数据进行修改,但是没有执行commit,这时候用户后悔了,这时候执行rollback,就可以直接回滚到之前的状态。undo日志保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC)

在MySQL5.6中,undo日志位于共享表空间中,共享表默认名称是ibdata文件
在MySQL5.7,undo日志就可以设置成独立的文件。

innodb_undo_directory = /data/undospace/ --设置undo日志的路径
innodb_undo_logs = 128 --定义InnoDB使用的回滚段数
innodb_undo_tablespaces = 4 --InnoDB使用的撤消表空间数。默认值为0。

当MySQL宕了,这时候重启,会检查数据的一致性(通过LSN)然后用redo日志重放,如果有一些事务是执行了但是未提交,MySQL可以检查redo日志这个记录是否提交,如果没有提交则利用undo日志回滚,因为undo日志是实时的,所以基本都是能会滚到前一个状态。这样也保证了数据的安全

参考链接:

展开阅读全文

没有更多推荐了,返回首页