四、事务日志以及事务异常如何应对
MySQL的版本号为8.0
在Innodb中事务的日志分为俩种,回滚日志、重做日志。
先来看一下俩个日志的存放位置吧!
在Linux下的MySQL事务日志存放在/var/lib/mysql这个位置中。
从上图中可以看到分别为ib_logfile、undo_俩个文件。
ib_logfile文件为重做日志
undo_文件为回滚日志
在这里估计有点小伙伴会有点迷糊这个回滚日志。
那是因为在MySQL5.6默认回滚日志没有进行独立表空间存储,而是存放到了ibdata文件中。
独立表空间存储从MySQL5.6后就已经支持了,但是需要自行配置。
在MySQL8.0是由innodb_undo_tablespaces 这个参数来设置回滚日志独立空间个数,这个参数的范围为0-128。
默认值为0表示不开启独立的回滚日志,且回滚日志存储在ibdata文件中。
这个参数是在初始化数据库时指定的,实例一旦创建这个参数是不能改动的。
如果设置的innodb_undo_tablespaces 值大于实例创建时的个数,则会启动失败。
1. 重做日志(redo log)(持久性实现原理)
事务的持久性就是通过重做日志来实现的。
当提交事务之后,并不是直接修改数据库的数据的,而是先保证将相关的操作记录到redo日志中。
数据库会根据相应的机制将内存的中的脏页数据刷新到磁盘中。
上图是一个简单的重做日志写入流程。
在上图中提到俩个陌生概念,Buffer pool、redo log buffer,这个俩个都是Innodb存储引擎的内存区域的一部分。
而redo log file是位于磁盘位置。
也就说当有DML(insert、update、delete)操作时,数据会先写入Buffer pool,然后在写到重做日志缓冲区。
重做日志缓冲区会根据刷盘机制来进行写入重做日志中。
这个机制的设置参数为innodb_flush_log_at_trx_commit,参数分别为0,1,2
上图即为重做日志的写入策略。
当这个参数的值为0的时,提交事务之后,会把数据存放到redo log buffer中,然后每秒将数据写进磁盘文件
当这个参数的值为1的时,提交事务之后,就必须把redo log buffer从内存刷入到磁盘文件里去,只要事务提交成功,那么redo log就必然在磁盘里了。
当这个参数的值为2的情况,提交事务之后,把redo log buffer日志写入磁盘文件对应的os cache缓存里去,而不是直接进入磁盘文件,1秒后才会把os cache里的数据写入到磁盘文件里去。
2. 服务器异常停止对事务如何应对(事务写入过程)
当参数为0时,前一秒的日志都保存在日志缓冲区,也就是内存上,如果机器宕掉,可能丢失1秒的事务数据。
当参数为1时,数据库对IO的要求就非常高了,如果底层的硬件提供的IOPS比较差,那么MySQL数据库的并发很快就会由于硬件IO的问题而无法提升。
当参数为2时,数据是直接写进了os cache缓存,这部分属于操作系统部分,如果操作系统部分损坏或者断电的情况会丢失1秒内的事务数据,这种策略相对于第一种就安全了很多,并且对IO要求也没有那么高。
小结
关于性能:0>2>1
关于安全:1>2>0
根据以上结论,所以说在MySQL数据库中,刷盘策略默认值为1,保证事务提交之后,数据绝对不会丢失。