mysql为什么需要undo log?
链接:https://www.zhihu.com/question/445644612/answer/1742967478
好问题。这里的关键点在于:对同一行数据你可能同时需要多个历史版本的数据
- 以下讨论以MySQL的InnoDB引擎为例
- 在InnoDB中,有三种日志跟事务的ACID关系都很大:
- undo log负责原子性,保护事务在exception或手动rollback时可以回滚到历史版本数据
- redo log负责落盘式持久性,保证事务提交后新的数据不会丢失
- binlog负责副本式持久性,可以将主节点上的数据复制到从节点,主节点crash后业务可以正常运转
- 可以看到, undo log只关心过去,redo log只关心未来
- 楼主提到『如果不提交数据,磁盘中的数据还是更新前的,事务回滚不更新数据就好了』。如果我们只记录一个历史版本数据,其它事务每次都只需要读取到最新版本的数据,的确是这样,这个就是Read Committed
- 但是,如果说你要备份整个数据库,整个事务可能会持续一个小时,同时有大量线上并发修改操作,我相信你一定希望读取到逻辑一致的数据。这时同一行数据就需要支持多个历史版本的数据了,这一招叫MVCC,对应Repeatable Read隔离级别,而记录多个历史版本数据的地方就叫undo log
- 实践中,对于面向个人业务的互联网在线业务,推荐Read Committed;对于分析性业务,推荐Repeatable Read(InnoDB的默认事务隔离级别)
- InnoDB将undo log作为数据的一部分存储到了redo log中,因此很多时候不太区分它们
链接:https://www.zhihu.com/question/445644612/answer/1742967478
好问题。这里的关键点在于:对同一行数据你可能同时需要多个历史版本的数据
- 以下讨论以MySQL的InnoDB引擎为例
- 在InnoDB中,有三种日志跟事务的ACID关系都很大:
- undo log负责原子性,保护事务在exception或手动rollback时可以回滚到历史版本数据
- redo log负责落盘式持久性,保证事务提交后新的数据不会丢失
- binlog负责副本式持久性,可以将主节点上的数据复制到从节点,主节点crash后业务可以正常运转
- 可以看到, undo log只关心过去,redo log只关心未来
- 楼主提到『如果不提交数据,磁盘中的数据还是更新前的,事务回滚不更新数据就好了』。如果我们只记录一个历史版本数据,其它事务每次都只需要读取到最新版本的数据,的确是这样,这个就是Read Committed
- 但是,如果说你要备份整个数据库,整个事务可能会持续一个小时,同时有大量线上并发修改操作,我相信你一定希望读取到逻辑一致的数据。这时同一行数据就需要支持多个历史版本的数据了,这一招叫MVCC,对应Repeatable Read隔离级别,而记录多个历史版本数据的地方就叫undo log
- 实践中,对于面向个人业务的互联网在线业务,推荐Read Committed;对于分析性业务,推荐Repeatable Read(InnoDB的默认事务隔离级别)
- InnoDB将undo log作为数据的一部分存储到了redo log中,因此很多时候不太区分它们
- 关于事务持久性的思考,写过一篇小文:
MySQL是原地更新记录的,事务的更新是直接作用到旧有记录,旧有记录被写到undo。同时,它又是steal的,意味着未提交的数据可以被持久化。undo有两个作用,第一,必须要有办法找回旧记录以回滚事务。同时,需要保存旧记录实现多版本。
当然,没有undo的数据库也有,比如PostgreSQL。它不会原地更新,更新就是插入一个新版本。当然,这样做的代价是浪费空间,失效记录太多了就会影响效率,需要定期的垃圾回收。
链接:https://www.zhihu.com/question/445644612/answer/2006134319
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了