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日志是实时的,所以基本都是能会滚到前一个状态。这样也保证了数据的安全
参考链接: