首页 > 数据库 >mysql为什么需要undo log?

mysql为什么需要undo log?

时间:2025-02-08 14:43:25浏览次数:6  
标签:事务 log undo InnoDB 版本 mysql 数据


链接:https://www.zhihu.com/question/445644612/answer/1742967478


好问题。这里的关键点在于:对同一行数据你可能同时需要多个历史版本的数据

  1. 以下讨论以MySQL的InnoDB引擎为例
  2. 在InnoDB中,有三种日志跟事务的ACID关系都很大:
    1. undo log负责原子性,保护事务在exception或手动rollback时可以回滚到历史版本数据
    2. redo log负责落盘式持久性,保证事务提交后新的数据不会丢失
    3. binlog负责副本式持久性,可以将主节点上的数据复制到从节点,主节点crash后业务可以正常运转
  3. 可以看到, undo log只关心过去,redo log只关心未来
  4. 楼主提到『如果不提交数据,磁盘中的数据还是更新前的,事务回滚不更新数据就好了』。如果我们只记录一个历史版本数据,其它事务每次都只需要读取到最新版本的数据,的确是这样,这个就是Read Committed
  5. 但是,如果说你要备份整个数据库,整个事务可能会持续一个小时,同时有大量线上并发修改操作,我相信你一定希望读取到逻辑一致的数据。这时同一行数据就需要支持多个历史版本的数据了,这一招叫MVCC,对应Repeatable Read隔离级别,而记录多个历史版本数据的地方就叫undo log
  6. 实践中,对于面向个人业务的互联网在线业务,推荐Read Committed;对于分析性业务,推荐Repeatable Read(InnoDB的默认事务隔离级别
  7. InnoDB将undo log作为数据的一部分存储到了redo log中,因此很多时候不太区分它们
 
链接:https://www.zhihu.com/question/445644612/answer/1742967478


好问题。这里的关键点在于:对同一行数据你可能同时需要多个历史版本的数据

  1. 以下讨论以MySQL的InnoDB引擎为例
  2. 在InnoDB中,有三种日志跟事务的ACID关系都很大:
    1. undo log负责原子性,保护事务在exception或手动rollback时可以回滚到历史版本数据
    2. redo log负责落盘式持久性,保证事务提交后新的数据不会丢失
    3. binlog负责副本式持久性,可以将主节点上的数据复制到从节点,主节点crash后业务可以正常运转
  3. 可以看到, undo log只关心过去,redo log只关心未来
  4. 楼主提到『如果不提交数据,磁盘中的数据还是更新前的,事务回滚不更新数据就好了』。如果我们只记录一个历史版本数据,其它事务每次都只需要读取到最新版本的数据,的确是这样,这个就是Read Committed
  5. 但是,如果说你要备份整个数据库,整个事务可能会持续一个小时,同时有大量线上并发修改操作,我相信你一定希望读取到逻辑一致的数据。这时同一行数据就需要支持多个历史版本的数据了,这一招叫MVCC,对应Repeatable Read隔离级别,而记录多个历史版本数据的地方就叫undo log
  6. 实践中,对于面向个人业务的互联网在线业务,推荐Read Committed;对于分析性业务,推荐Repeatable Read(InnoDB的默认事务隔离级别
  7. InnoDB将undo log作为数据的一部分存储到了redo log中,因此很多时候不太区分它们
  8. 关于事务持久性的思考,写过一篇小文:
 

MySQL是原地更新记录的,事务的更新是直接作用到旧有记录,旧有记录被写到undo。同时,它又是steal的,意味着未提交的数据可以被持久化。undo有两个作用,第一,必须要有办法找回旧记录以回滚事务。同时,需要保存旧记录实现多版本。

当然,没有undo的数据库也有,比如PostgreSQL。它不会原地更新,更新就是插入一个新版本。当然,这样做的代价是浪费空间,失效记录太多了就会影响效率,需要定期的垃圾回收。




链接:https://www.zhihu.com/question/445644612/answer/2006134319

标签:事务,log,undo,InnoDB,版本,mysql,数据
From: https://www.cnblogs.com/tiancai/p/18704226

相关文章