mysql日志生成规则_mysql事务日志

在数据库系统中,事务的原子性和持久性是由事务日志(transaction log)实现的。事务需要由支持事务的存储引擎来实现。MySQL的存储引擎主要是InnoDB和MyISAM, InnoDB是MySQL的默认事务引擎,但MyISAM不支持事务。

mysql在具体的实现上,使用的就是回滚日志(undo log)和重做日志(redo log)。前者用于对事务的影响进行撤销,保证原子性和一致性,后者在错误处理时对已经提交的事务进行重做(如在事务提交后,数据没来得及写到磁盘就宕机时,在下次重新启动后能够成功恢复为新的数据),保证持久性。

undo log

由于操作并不具有原子性,并且可以再分为多个操作,当这些操作出现错误或抛出异常时,整个操作就可能不会继续执行下去,而已经进行的操作造成的副作用就可能造成数据更新的丢失或者错误。想要保证事务的原子性,就需要在异常发生时,对已经执行的操作进行回滚,而在 MySQL 中,恢复机制是通过回滚日志(undo

log)实现的,所有事务进行的修改都会先记录到这个回滚日志中,然后再对数据库中的对应行进行写入。

在日志块中写入的日志纪录有以下几种不同形式:

:事务 T 开始执行。

[ :事务 T 提交完成,表示该事务不会再对数据库进行任何修改

:事务 T 被中止,该事务未对数据库进行的更新被放弃,己对数据库进行的更新被撤销。

:事务 T 修改了数据库元素 X 的值, X 的原值是 V 。

为了使得数据库能够从系统故障或崩溃中恢复,Undo 机制下事务必须遵守两条规则。这两条规则规定了缓冲区管理器应执行的操作和事务提交时要立即执行的操作。

规则 1 :事务 T 一旦修改了数据库元素 X , 要求保证在 X 的新值写入磁盘前,先将<T , X , V>日志记录写入磁盘中。

规则 2 :事务 T 己经成功提交完成,要求在事务 T 对数据库的所有修改均写入磁盘后,再尽快将<Commit T>日志纪录写入磁益中。

两条规则的实质是规定了事务写入磁盘内容的先后次序,首先写入修改数据库元素的日志记录,然后对数据库元素本身进行修改。最后写入各提交的日志记录。

当数据库系统发生故障或崩溃时,使用Undo 日志来保证操作原子性的机制是:首先恢复管理器将事务划分为已提交和未提交两种状态,对它们进行不同的处理。

一种情况是,查看 Undo 日志记录发现某事务有提交记录,则根据规则 2 可以判断,该事务对数据库所做的全部修改均己从主存写入磁盘。所以这一事务不会造成不一致的数据库状态,对于这种已提交事务不需要进行任何处理。

另一种情况是,查看 undo日志记录发现某一事务有开始记录但没有提交记录,则可能数据库故障或崩溃前该事务对数据库的部分修改己写入磁益,而另一部分修改还保存在主存中而未写入磁盘,甚至可能还有部分修改在主存中都还未完成,这种事务属于未提交事务。由于不能确定该事务对数据库的修改是否己全部完成并写入磁盘.所以该事务必须被撤销并将其对数据库元素的修改恢复原值。根据规则 1 的规定,如果数据库故障或崩溃前,事务修改了数据库元素 X 的值,则日志中必定写入了<T , X , V>日志纪录,并且该日志记录己写入磁盘.所以只需要将数据库元素 X 的值恢复为 V 即可。

恢复管理器使用 Undo 日志记录对数据库进行恢复后,对数据库进行的正常操作可以重新开始,可以开始新事务的执行。

事务开始之前,系统就开始生成undo

log,当事务提交之后,undo

log并不能立马被删除,而是放入待清理的链表,由purge线程去处理。

回滚日志除了能够在发生错误或者用户执行 ROLLBACK 时提供回滚相关的信息,它还能够在整个系统发生崩溃、数据库进程直接被杀死后,当用户再次启动数据库进程时,还能够立刻通过查询回滚日志将之前未完成的事务进行回滚.

因为回滚只对未进行commit的事务有效,回滚日志并不能将数据库物理地恢复到执行语句或者事务之前的样子;它是逻辑日志,当回滚日志被使用时,它只会按照日志逻辑地将数据库中的修改撤销掉。

redo log

与原子性一样,事务的持久性也是通过日志来实现的,MySQL 使用重做日志(redo log)实现事务的持久性,重做日志由两部分组成,一是内存中的重做日志缓冲区,因为重做日志缓冲区在内存中,所以它是易失的,另一个就是在磁盘上的重做日志文件,它是持久的。redo Log 记录的是新数据的备份。在事务提交前,只要将redo Log 持久化即可,不需要将数据持久化。

当系统崩溃时,虽然数据没有持久化,但是redo Log 已经持久化。系统可以根据redo Log 的内容,将所有数据恢复到新的状态。

在事务引擎上的每一次写(delete\update\create)操作都需要两次写入磁盘操作:

1、先写入日志文件中

写入日志文件中的仅仅是操作过程,而不是操作数据本身(如要删除一行数据会先在日志文件中将此行标记为删除,但是数据库中的数据文件并没有发生变化),存储引擎在修改表的数据的时候只需要修改其内存拷贝,再把该行为记录到持久在磁盘的事务日志中。而不用每次都将修改的数据本身持久到磁盘。事务日志持久化采用的是追加方式,因此写日志的操作是磁盘上一小块区域的顺序IO,而不像随机IO需要磁盘在多个地方移动。所以采用事务日志的方式相对来说要快的多。

2、写入数据库文件中

事务日志持久后,内存中的修改在后台慢慢的刷回磁盘。

由于先写日志,后写数据库,所以被称为(write ahead logging)预写日志。期间如果系统发生崩溃,存储引擎在重启的时候依靠事务日志自动恢复这部分被修改数据。

事务开始之后就产生redo log,redo log的落盘并不是随着事务的提交才写入的,而是在事务的执行过程中,便开始写入redo log文件中。当我们在一个事务中尝试对数据进行修改时,它会先将数据从磁盘读入内存,并更新内存中缓存的数据,然后生成一条重做日志并写入重做日志缓存,当事务真正提交时,MySQL 会将重做日志缓存中的内容刷新到重做日志文件,再将内存中的数据更新到磁盘上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值