MYSQL事务

事务简介

    事务是数据库区别于文件系统的最重要特征之一。事务可以保证数据库从一个状态转移到另一个状态,也就是说在一个事务中的语句要么全部一起提交(所有修改都会保存),要么回滚(所有修改都不会保存)。

    事务的性质:原子性,一致性,隔离性,持久性(ACID)保证一个事务的正确执行。每种性质具体含义具体参考:https://blog.csdn.net/puliao4167/article/details/89043612

事务的分类

    事务可以分为扁平事务,带有保存点的扁平事务,链事务,嵌套事务,分布式事务

  • 扁平事务,是平常用的最多的事务,所有的操作处于同一个层次,由begin开始,由commit或者rollback结束,其间的操作语句都是原子性的,要么都执行,要么都不执行。
  • 带有保存点的扁平事务,除了支持扁平的事务外,还允许在回滚的时候,可以回滚到同一事物的较早的状态,保存点是用来提醒系统记住当前的状态。如果没有特殊的(显式的)保存点,在回滚的时候默认会回滚到事务起始处,
  • 链事务,可以视为保存点模式的另一种方式,带有保存点的扁平事务中的保存点是易失的,而非持久的,当系统发生崩溃时,保存点即会消失,事务要从头开始执行。链事务的思想是:在提交一个事务的时候,释放不需要的数据,将要处理的上下文隐式的传递给下一个开启的事务(形成一个链状)
  • 嵌套事务是一个层次结构框架,一个顶级事务中调用子事务
  • 分布式事务是在分布式的环境下运行的扁平事务

redo日志

    首要要清楚,事务ACID中的隔离性是由锁机制来实现的,而另外的三个性质原子性,持久性,一致性由redo日志,undo日志保证。

    redo log(重做日志)是有两个部分组成:一个是在内存中的重做日志缓冲,另一个是在磁盘中的重做日志文件。在InnoDB存储引擎中,大部分情况下 Redo是物理日志,记录的是数据页的物理变化。Redo log的主要作用是用于数据库的崩溃恢复。redo的流程如下:

  1. 先将原始数据从磁盘中读入内存中来,修改数据的内存拷贝
  2. 生成一条重做日志并写入redo log buffer,记录的是数据被修改后的值
  3. 当事务commit时,将redo log buffer中的内容刷新到 redo log file,对 redo log file采用追加写(顺序写)的方式
  4. 定期将内存中修改的数据刷新到磁盘中

    从上图中可以看出,Innodb其通过Force Log at Commit 机制实现事务的持久性,即当事务提交时,先将 redo log buffer 写入到 redo log file 进行持久化,待事务的commit操作完成时才算完成。这种做法也被称为 Write-Ahead Log(预先日志持久化),在持久化一个数据页之前,先将内存中相应的日志页持久化。

    Force Log at Commit机制就是靠InnoDB存储引擎提供的参数 innodb_flush_log_at_trx_commit来控制的,该参数可以控制 redo log刷新到磁盘的策略,设置该参数值也可以允许用户设置非持久性的情况发生,具体如下:

  • 当设置参数为1时,(默认为1),表示事务提交时必须调用一次fsync操作,最安全的配置,保障持久性
  • 当设置参数为2时,则在事务提交时只做write操作,只保证将redo log buffer写到系统的页面缓存中,不进行fsync操作,因此如果MySQL数据库宕机时 不会丢失事务,但操作系统宕机则可能丢失事务
  • 当设置参数为0时,表示事务提交时不进行写入redo log操作,这个操作仅在master thread 中完成,而在master thread中每1秒进行一次重做日志的fsync操作,因此实例 crash 最多丢失1秒钟内的事务。(master thread是负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性)

undo日志

    undo log主要记录的是数据的逻辑变化,为了在发生错误时回滚之前的操作,需要将之前的操作都记录下来,然后在发生错误时才可以回滚。redo log存放在内存的重做日志文件中,undo 存放在数据库中一个特殊的段中(undo 段),是一种逻辑日志。undo有两个作用,一是记录操作用于事务回滚,第二是MVCC。在回滚的时候,它实际上是做的相反的工作,比如一条INSERT ,对应一条 DELETE,对于每个UPDATE,对应一条相反的 UPDATE,将修改前的行放回去,所以其要在DML语句修改之前记录数据。

    当进行insert或者update修改聚簇索引前,要记录undo日志,需要注意的是,记录undo日志,同时也要记录redo日志。以下一个例子

假设有A、B两个数据,值分别为1,2.
1. 事务开始
2. 记录A=1到undo log
3. 修改A=3
4. 记录A=3到 redo log
5. 记录B=2到 undo log
6. 修改B=4
7. 记录B=4到redo log
8. 将redo log写入磁盘
9. 事务提交

 

参考《高性能mysql》、《MYSQL技术内幕 Innodb存储引擎》

浅谈mysql事务中的redo和undo  https://www.jianshu.com/p/20e10ed721d0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值