【MySQL】事物日志

网友投稿 676 2022-05-28

查看事物日志

show engine innodb status

查看日志文件设置状态

show varibales like 'innodb_%';

innnodb_log_file_in_group中设置几组事物日志,默认是2;

innodb_log_group_home_dir事物日志存放目录,不设置会存在数据库的默认文件目录下

innodb存储引擎可将所有数据存放于ibdata*的共享表空间,也可以将每张表存放于独立的ibd文件的独立表空间

注意:在Mysql中对于数据来说,最为重要的是日志文件

重做日志:redo log = ib_logfile

回滚日志:undo log = ibdata

回滚日志

事物的属性与一个原子性,通俗的解释就是一条绳上的蚂蚱。专业点就是一系列的操作,要么全部执行,要么都不执行

想要保证事物的原子性,就需要在异常发生时,对已经执行的操作进行回滚,而在mysql中,恢复机制是通过回滚日志实现的,也就是undo log,所有的事物进行的修改都会先记录到这个回滚日志中,然后在对数据库中的对应进行写入

注意:系统发生崩溃,数据库进程直接被杀死后,当用户再次启动数据库进程时,还能够立刻通过查询回滚日志将之前未完成的事物进程回滚,这也就需要回滚日志必须先于数据持久化到磁盘上,是我们需要先写日志后写数据库的主要原因

在日志文件中,在事物中使用的每一条insert都对应了一条delete,没一条uodate也都对应一条相反的update语句

重做日志

与原子性一样,事务的持久性也是通过日志来实现的,MySQL 使用重做日志(redo log)实现事务的持久性,重做日志由两部分组成,一是内存中的重做日志缓冲区,因为重做日志缓冲区在内存中,所以它是易失的,另一个就是在磁盘上的重做日志文件,它是持久的。

在事务写入过程

当我们在一个事务中尝试对数据进行写时,它会先将数据从磁盘读入内存,并更新内存中缓存的数据,然后生成一条重做日志并写入重做日志缓存,当事务真正提交时,MySQL 会将重做日志缓存中的内容刷新到重做日志文件,再将内存中的数据更新到磁盘上,图中的第 4、5 步就是在事务提交时执行的。

回滚日志和重做日志

到现在为止我们了解了 MySQL 中的两种日志,回滚日志(undo log)和重做日志(redo log);在数据库系统中,事务的原子性和持久性是由事务日志(transaction log)保证的,在实现时也就是上面提到的两种日志,前者用于对事务的影响进行撤销,后者在错误处理时对已经提交的事务进行重做,它们能保证两点:

【MySQL】事物日志

发生错误或者需要回滚的事务能够成功回滚(原子性);

在事务提交后,数据没来得及写会磁盘就宕机时,在下次重新启动后能够成功恢复数据(持久性);

在数据库中,这两种日志经常都是一起工作的,我们可以将它们整体看做一条事务日志,其中包含了事务的 ID、修改的行元素以及修改前后的值。

事务日志流程

checkpoint,即检查点。在undolog中写入检查点,表示在checkpoint前的事务都已经完成commit或者rollback了,也就是检查点前面的事务已经不存在数据一致性的问题了(此处暂时不会深入解释)

Innodb的事务日志是指Redo log,简称Log,保存在日志文件ib_logfile里面(去mysql数据目录下看下)。Innodb还有另外一个日志Undo log,但Undo log是存放在共享表空间里面的(ibdata*文件,存储的是check point日志序列号)。

Innodb的一条事务日志共经历4个阶段:

1)创建阶段:事务创建一条日志;

2)日志刷盘:日志写入到磁盘上的日志文件;(ib_logfile里面)

3)数据刷盘:日志对应的脏页数据写入到磁盘上的数据文件;

4)写CKP:日志被当作Checkpoint写入日志文件;(ib_data里面)

innodb_flush_log_at_trx_commit 参数解析

0:log buffer将每秒一次地写入log file中,并且log file的flush(刷到磁盘)操作同时进行。该模式下在事务提交的时候,不会主动触发写入磁盘的操作。

1:每次事务提交时MySQL都会把log buffer的数据写入log file,并且flush(刷到磁盘)中去,该模式为系统默认。

2:每次事务提交时MySQL都会把log buffer的数据写入log file,但是flush(刷到磁盘)操作并不会同时进行。该模式下,MySQL会每秒执行一次 flush(刷到磁盘)操作。

关于性能:0>2>1

关于安全:1>2>0

注意事项

innodb_flush_log_at_trx_commit=0,表示每隔一秒把log buffer刷到文件系统中(os buffer)去,并且调用文件系统的“flush”操作将缓存刷新到磁盘上去。也就是说一秒之前的日志都保存在日志缓冲区,也就是内存上,如果机器宕掉,可能丢失1秒的事务数据。

innodb_flush_log_at_trx_commit=1,表示在每次事务提交的时候,都把log buffer刷到文件系统中(os buffer)去,并且调用文件系统的“flush”操作将缓存刷新到磁盘上去。这样的话,数据库对IO的要求就非常高了,如果底层的硬件提供的IOPS比较差,那么MySQL数据库的并发很快就会由于硬件IO的问题而无法提升。

innodb_flush_log_at_trx_commit=2,表示在每次事务提交的时候会把log buffer刷到文件系统中去,但并不会立即刷写到磁盘。如果只是MySQL数据库挂掉了,由于文件系统没有问题,那么对应的事务数据并没有丢失。只有在数据库所在的主机操作系统损坏或者突然掉电的情况下,数据库的事务数据可能丢失1秒之类的事务数据。这样的好处,减少了事务数据丢失的概率,而对底层硬件的IO要求也没有那么高(log buffer写到文件系统中,一般只是从log buffer的内存转移的文件系统的内存缓存中,对底层IO没有压力)。

MySQL 数据库

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Python MYSQL 索引的原理
下一篇:bootsect启动代码分析
相关文章