关于PostgreSQL的事务快照的延迟

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
简介: PostgreSQL提供了几个事务快照函数,实测发现,通过这些函数取到的事务快照可能要比自己预想的要有一个延迟。 1. 功能说明 几个事务快照函数的功能说明参考PostgreSQL手册。
PostgreSQL提供了几个事务快照函数,实测发现,通过这些函数取到的事务快照可能要比自己预想的要有一个延迟。

1. 功能说明

几个 事务快照函数的功能说明参考PostgreSQL手册。
http://58.58.27.50:8079/doc/html/9.3.1_zh/functions-info.html
-----------------------------------------------------------------------------------------------------------

Table 9-56显示的函数在一个输出形式中提供服务器事务信息。 这些函数的主要用途是为了确定在两个快照之间有哪个事务提交。

Table 9-56. 事务ID和快照

名字 返回类型 描述
txid_current() bigint 获取当前事务 ID
txid_current_snapshot() txid_snapshot 获取当前快照
txid_snapshot_xip(txid_snapshot) setof bigint 获取在快照中进行中的事务ID
txid_snapshot_xmax(txid_snapshot) bigint 获取快照的 xmax
txid_snapshot_xmin(txid_snapshot) bigint 获取快照的xmin
txid_visible_in_snapshot(bigint, txid_snapshot) boolean 在快照中事务ID是否可见?(不使用子事务ID)

内部事务 ID 类型(xid)是32位,每40亿事务循环。然而这些函数导出一个64位格式, 是使用一个"epoch"计数器扩展,所以在安装过程中不会循环。 这些函数使用的数据类型txid_snapshot,存储在某时刻事物ID可见性的信息。 其组件描述在Table 9-57


Table 9-57. 快照组件

名字 描述
xmin 最早的事务ID(txid)仍然活动。所有较早事务将是可见提交了,或者要么死掉回滚了。
xmax 首先作为尚未分配的txid。所有大于或等于此的txids作为这时的快照都是尚未开始的,因此不可见。
xip_list 在当前快照活动的txids。这个列表只包含在xmin和xmax 之间的活动txids;有可能活动的txids高于xmax。 一个xmin

txid_snapshot的文本表示为:xmin:xmax:xip_list。 例如10:20:10,14,15意思为:xmin=10, xmax=20, xip_list=10, 14, 15。

-----------------------------------------------------------------------------------------------------------

2. 实际测试

通过在PostgreSQL9.3上实际测试,进一步了解了一些细节。
1)单独调用txid_current_snapshot()函数,不会产生新的事务

  1. postgres=# select txid_current_snapshot();
  2.  txid_current_snapshot
  3. -----------------------
  4.  3928129:3928129:
  5. (1 row)

  6. postgres=# select txid_current_snapshot();
  7.  txid_current_snapshot
  8. -----------------------
  9.  3928129:3928129:
  10. (1 row)
3928129是尚未分配的事务ID,两次执行,它的值没有变化。

2)单独调用txid_current()函数,会产生新的事务

  1. postgres=# select txid_current();
  2.  txid_current
  3. --------------
  4.       3928129
  5. (1 row)

  6. postgres=# select txid_current();
  7.  txid_current
  8. --------------
  9.       3928130
  10. (1 row)

  11. postgres=# select txid_current_snapshot();
  12.  txid_current_snapshot
  13. -----------------------
  14.  3928131:3928131:
  15. (1 row)

3)对不影响数据库状态的查询不会产生新事务ID。

  1. postgres=# select txid_current_snapshot();
  2.  txid_current_snapshot
  3. -----------------------
  4.  3928131:3928131:
  5. (1 row)

  6. postgres=# select * from msg limit 1;
  7.    id | msg
  8. --------+--------
  9.  182002 | 182002
  10. (1 row)

  11. postgres=# select txid_current_snapshot();
  12.  txid_current_snapshot
  13. -----------------------
  14.  3928131:3928131:
  15. (1 row)

4)事务快照可能存在滞后
先在session1开一个事务。
session1:
  1. postgres=# begin;
  2. BEGIN
  3. postgres=# select txid_current();
  4.  txid_current
  5. --------------
  6.       3928131
  7. (1 row)

但是在session2中却看不到这个事务(事务快照的xmax没有变化)
session2:
  1. postgres=# select txid_current_snapshot();
  2.  txid_current_snapshot
  3. -----------------------
  4.  3928131:3928131:
  5. (1 row)

session1提交后,session2的快照得到更新。
session1:
  1. postgres=# commit;
  2. COMMIT

session2:
  1. postgres=# select txid_current_snapshot();
  2.  txid_current_snapshot
  3. -----------------------
  4.  3928132:3928132:
  5. (1 row)

5)事务快照可能不包含自身事务
把4)引申一下,就会发现事务快照对当前事务也可能存在滞后,即事务快照不包含自身事务。自身事务从快照看就是一个“未来的”事务。

  1. postgres=# begin;
  2. BEGIN
  3. postgres=# select txid_current_snapshot();
  4.  txid_current_snapshot
  5. -----------------------
  6.  3928132:3928132:
  7. (1 row)
  8. postgres=# select txid_current();
  9.  txid_current
  10. --------------
  11.       3928132
  12. (1 row)

  13. postgres=# select txid_current_snapshot();
  14.  txid_current_snapshot
  15. -----------------------
  16.  3928132:3928132:
  17. (1 row)

6)任何一个创建了新事务ID的事务结束时,所有会话的事务快照得到更新
在session1开一个事务,但在session2的事务快照中看不到这个事务。
session1:
  1. postgres=# begin;
  2. BEGIN
  3. postgres=# select txid_current();
  4.  txid_current
  5. --------------
  6.      3928142
  7. (1 row)

session2:
  1. postgres=# begin;
  2. BEGIN
  3. postgres=# select txid_current();
  4.  txid_current
  5. --------------
  6.       3928143
  7. (1 row)

  8. postgres=# select txid_current_snapshot();
  9.  txid_current_snapshot
  10. -----------------------
  11.  3928142:3928142:
  12. (1 row)

在另一个会话session3中任意提交或回滚一个需要创建新事务ID的事务,session2就可以看到session1的事务了。
session3:
  1. postgres=# select txid_current();
  2.  txid_current
  3. --------------
  4.      3928144
  5. (1 row)

session2:
  1. postgres=# select txid_current_snapshot();
  2.   txid_current_snapshot
  3. -------------------------
  4.  3928142:3928145:3928142
  5. (1 row)
需要注意的是:即使这样, session2的事务快照中记录的活动事务中也没有包含自身事务( 3928143)。是不是 事务快照中的 活动事务一定不包含自身事务?这个手册没有说。

3.总结

PostgreSQL可能出于性能的考虑,延迟了快照的更新。每次事务结束时更新一次全局的事务快照,而不是在事务开始时更新快照。但是这个延迟不影响事务的可见性判断。如果一个活动的事务没有出现在事务快照中,表示自这个事务创建后,还没有发生任何事务提交,也就是事务快照保存的还是这个事务开始前的状态。进一步,这个活动的事务ID必然大于等于事务快照的xmax属性,对快照来说这是一个"未来的"事务,是不可见的,这与活动事务的可见性结果一致。
简而言之,PostgreSQL中的事务快照是上一次系统发生事务提交或回滚时的事务快照,而不是获取事务快照时的。








相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
存储 SQL 监控
22 PostgreSQL 监控3PostgreSQL 性能快照和图形化分析工具 pg_stats_info 的使用|学习笔记
快速学习22 PostgreSQL 监控3PostgreSQL 性能快照和图形化分析工具 pg_stats_info 的使用
900 0
22 PostgreSQL 监控3PostgreSQL 性能快照和图形化分析工具 pg_stats_info 的使用|学习笔记
|
SQL 缓存 运维
PostgreSQL 事务号回卷分析
## XID 定义 xid 是个啥东西?xid 就是 PostgreSQL 里面的事务号,每个事物都会分配一个 xid。PostgreSQL 数据中每个元组头部都会保存着 插入 或者 删除 这条元组的事务号,即 xid,然后内核通过这个 xid 进行元组的可见性判断。简单理解,比如有两个事务,xid1=200,xid2=201,那么 xid1 中只能看到 t_xmin 200 的元组。 ```c
|
4月前
|
SQL 存储 关系型数据库
PolarDB-X Operator 基于两次心跳事务的指定时间点恢复方案介绍
本文将介绍,PolarDB-X Operator将在事务策略为XA事务或者TSO事务时,如何实现全局一致的任意时间点恢复,提出了基于两次心跳事务的恢复方案。
|
7月前
|
存储 关系型数据库 数据库
数据库内核那些事|PolarDB X-Engine:如何构建1/10成本的事务存储引擎?
X-Engine引擎是PolarDB为用户提供的低成本,高性价比的解决方案,LSM-tree分层存储结合标准zstd压缩,在性能和成本做到了很好的平衡。在标准sysbench场景下,存储空间相比InnoDB引擎减少60%,读写性能降低10-20%。
数据库内核那些事|PolarDB X-Engine:如何构建1/10成本的事务存储引擎?
|
9月前
|
存储 SQL 关系型数据库
postgresql snapshot 快照源码解读
本文主要介绍数据库事务快照,分别从源码实现角度和从SQL使用角度来剖析,快照的原理,作用,用途,以及在实现过程中存在的一些差异。
348 3
|
9月前
|
关系型数据库 PostgreSQL
PostgreSQL事务提交日志与CLOG操作初步认识
PostgreSQL事务提交日志与CLOG操作初步认识
150 0
|
10月前
|
Oracle 关系型数据库 数据库
PostgreSQL技术大讲堂 - 第20讲:事务概述与隔离级别
PostgreSQL从小白到专家,技术大讲堂 - 第20讲:事务概述与隔离级别
188 2
|
10月前
|
SQL Oracle NoSQL
Flink CDC 2.4 正式发布,新增 Vitess 数据源,PostgreSQL 和 SQL Server CDC 连接器支持增量快照,升级 Debezium 版本
Flink CDC 2.4 正式发布,新增 Vitess 数据源,PostgreSQL 和 SQL Server CDC 连接器支持增量快照,升级 Debezium 版本
1057 1
Flink CDC 2.4 正式发布,新增 Vitess 数据源,PostgreSQL 和 SQL Server CDC 连接器支持增量快照,升级 Debezium 版本
|
11月前
|
SQL 前端开发 关系型数据库
开源分布式数据库PolarDB-X源码解读——PolarDB-X源码解读(十一):事务的一生
开源分布式数据库PolarDB-X源码解读——PolarDB-X源码解读(十一):事务的一生
204 0
|
存储 Kubernetes Cloud Native
Longhorn+K8S+KubeSphere云端数据管理,实战 Sentry PostgreSQL 数据卷增量快照/备份与还原
云端实验环境配置 1. VKE K8S Cluster 2.Kubesphere v3.3.1 集群可视化管理 3.Longhorn 1.14
351 0