链接: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
标签:事务,log,undo,InnoDB,版本,mysql,数据 From: https://www.cnblogs.com/tiancai/p/18704226