mysql为什么需要undo 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中,因此很多时候不太区分它们
 

链接: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

posted @   甜菜波波  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示