MySQL实现事务的提交和回滚

什么是事务?
事务是数据库中一系列的访问和更新组成的逻辑执行单元,事务的逻辑单元中可以是一条SQL语句,也可以是一段SQL逻辑,这段逻辑要么全部执行成功,要么全部执行失败。
也就是说事务就是用来保证一系列操作的原子性,
数据库为了保证事务的原子性和持久性,引入了redo log 和 undo log
redo log
redo log是重做日志,是物理日志,记录的是物理数据页的修改,它用来恢复叫后的物理数据页,
MySQL实现事务的提交和回滚_第1张图片
redo log 分为两部分:

  1. 内存中的redo log buffer是日志缓冲区,这部分数据容易丢失

  2. 磁盘中的redo log file是日志文件,这部分数据已经持久化磁盘,不容易丢失
    SQL操作数据库之前,会先记录重做日志,为了保证效率会先写到日志缓冲区中(redo log buffer),再通过缓冲区写到磁盘文件中进行持久化,存在缓冲区就说明数据不是实时的写到redo log file 中,在这时服务器突然断电,那么redo log会丢失数据。
    在MySQL中可以自己控制 redo log buffer 刷新到log file中的频率,通过innodb_flush_log_trx_commit参数可以设置事务提交的log buffer 如何保存到log file中,innodb_flush_log_trx_commit参数有三个值(0,1,2)

  3. 为1表示事务每次提交都会将log buffer写入到os buffer,并调用操作系统的fsync()方法将日志写入log file,这种方式的好处是就算MySQL崩溃也不会丢数据,redo log file保存了所有已提交事务的日志,MySQL重新启动后会通过redo log file进行恢复。但这种方式每次提交事务都会写入磁盘,IO性能较差

  4. 为0表示事务提交时不会将log buffer写入到os buffer中,而是每秒写入os buffer然后调用fsync()方法将日志写入log file,这种方式在MySQL系统崩溃时会丢失大约1秒钟的数据

  5. 为2表示事务每次提交仅将log buffer写入到os buffer中,然后每秒调用fsync()方法将日志写入log file,这种方式在MySQL崩溃时也会丢失大约1秒钟的数据
    undo log
    undo log 是回滚日志,用来回滚行记录到一个版本,undo log一般是逻辑日志,根据行的数据变化进行记录
    undo log 跟redo log一样也是在SQL操作数据之前记录的,也就是SQL操作先记录日志,在进行操作数据
    MySQL实现事务的提交和回滚_第2张图片
    如上图所示,SQL操作之前会先记录redo log、undo log到日志缓冲区,日志缓冲区的数据会记录到os buffer中,再通过调用fsync()方法将日志记录到log file中

undo log记录的是逻辑日志,可以简单的理解为:当insert一条记录时,undo log会记录一条对应的delete语句;当update一条语句时,undo log记录的是一条与之操作相反的语句

当事务需要回滚时,可以从undo log中找到相应的内容进行回滚操作,回滚后数据恢复到操作之前的状态

undo日志还有一个用途就是用来控制数据的多版本(MVCC),在《InnoDB存储引擎中的锁》一文中讲到MVCC是通过读取undo日志中数据的快照来进行多版本控制的

undo log是采用段(segment)的方式来记录的,每个undo操作在记录的时候占用一个undo log segment。

另外,undo log也会产生redo log,因为undo log也要实现持久性保护

总结一下

MySQL中如何实现事务提交和回滚的?

  1. 为了保证数据的持久化,数据库在执行SQL操作数据之前会先记录redo log和undo log
  2. redo log 是重做日志,通常物理日志,记录的是物理数据页的修改,它用来恢复提交后的物理数据页
  3. undo log是回滚日志,用来会滚滚行记录到一个版本,undo log一般是逻辑日志,根据行的数据变化进行记录
  4. redo、undo log 都是写先写到日志缓冲区,在通过缓冲区写到磁盘日志文件中进行持久化保存
  5. undo日志还有一个用途就是用来控制数据的多版本

简单的理解:
redo log是用来恢复数据的,用于保障已提交事务的持久化
undo log是用来回滚事务的,用户保障未提交事务的原子性

你可能感兴趣的:(数据库,mysql)