前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >为什么PostgreSQL的回滚是瞬间完成的?

为什么PostgreSQL的回滚是瞬间完成的?

作者头像
数据库架构之美
发布2021-01-28 15:37:37
1.8K0
发布2021-01-28 15:37:37
举报
文章被收录于专栏:数据库架构之美

pg数据库的回滚是瞬间完成的。看到这句话是不是觉得pg很先进,确实是这样,但是也是有代价的,下面聊一聊这个问题。

事务的回滚和数据库的MVCC机制是分不开的,先看看以oracle和mysql为代表的基于undo表空间实现的mvcc。以mysql为例,mysql undo两个最重要的功能,一个是实现了写不阻塞读,或者说是mvcc,另外一个当然就是事务的回滚。

MySQL在进行数据操作时,先将数据备份到undo段中,然后再进行数据的修改,这样未提交的数据会保存一份前镜像在undo中,同时数据行上的rollpointer指针指向undo段上的老数据,同时老数据由于有可能经过多次更新,所以具有多个版本,多个数据版本之间通过链表链接。数据库如果查询正在更改的数据,会通过指针查到undo中的前镜像,这样就实现了读写的互不阻塞。需要回滚时,数据库会使用undo的旧数据恢复回来,所以基于undo的回滚是有一个过程的,需要将数据反向操作到原来的状态,这个反向操作可能对于数据库是灾难性的,同时undo也是会产生redo的。

所以对于undo实现的mvcc来说长事务或者大事务可能对数据库产生灾难的影响,如果一个事务长期不提交,那么大量的undo数据将一直保留,而且不能被清空覆盖。另外一个是跑批,大批量的更新如果被异常中断,那么回滚需要将这个大操作反向再做一次,对数据库的消耗是非常大的。当然mysql对于delete做了一定优化,delete只是打了标识位。

再说说pg的回滚,pg的回滚是瞬间完成的,这个是为什么呢?我们知道pg没有undo表空间,通过将多版本的数据真实存储在数据页里来实现mvcc,读取一条未提交数据行会去读取以前的数据版本,而以前的数据版本不是存在于undo而是和真实数据一起存放在数据页中,过期的元组会不定期进行清理,释放空间。

不敢说pg的数据多版本和mysql的undo孰优孰劣,对于最大的诟病就是空间的膨胀,过期的数据页需要不定期清理,但是反过来想,如果把旧版本放在undo里岂不也是一样在事务提交后需要清理,而且undo限制死了最大使用的undo段,这在数据库的设计上我觉得不是优美的。而pg这样设计的好处也非常明显,就是显著提高了dml的性能,因为在做更新类操作时,不需要去写undo,旧的数据就在原地不动,我只需要插入新的数据,这样性能非常好,测试过pg的更新的性能能够达到20w条每秒,这是一个非常恐怖的性能数据。

所以对于pg来说,插入就是插入元组并改xmin值,更新也是插入元组并更改xmin,xmax值,删除只是改xmax值。知道了pg的多版本原理,再看看pg的回滚就很好理解了,比如说我正在做一个1G大小的表的全表update更新,我们会在更新的过程中看到表的大小一直在变大,更新完了之后表的大小会变成原来的正好2倍,这就是因为老版本的数据并没有当时删除,而是插入了更新后的值。那么现在比如在更新过程中比如500M的地方将语句杀掉,那么可以看到这个表的大小停留在1.5G大小,也就是说已经插入的500M的数据不需要当时就清理掉的,不需要挨个回滚的。这也就是为什么pg的回滚很快的原因。如果这时做个vacuum full这个表又会恢复到1G大小。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据库架构 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档