了解Postgres中的virtualxid事务类型

10

我正在尝试理解Postgres中的锁,目前我已经了解到以下内容:

  • pg_locks包含锁信息
  • 在Postgres中,所有语句都在事务内运行(显式/隐式)。(Postgres 9.0高性能)

据我所知,虚拟事务ID(virtualxids)并非真正的事务,事务ID(transactionidxid)才是表示事务的标志。

当我简单地连接到psql shell,并查询pg_locks表时,就已经存在一个虚拟事务ID了。

我没有启动事务或运行查询,那么为什么会创建这个虚拟事务ID呢?是因为这个连接可能会在将来启动一个事务吗?

我在这里缺少了什么?


我对Postgres相对较新,但我知道它使用MVCC,仅为写入操作加锁,而不是读取操作。因此,像你所说的那样,select语句将在隐式事务中运行,但不应获取任何锁定。 - Brandon
没错,但是如果虚拟xid不获取任何锁,仅仅是客户端连接创建了虚拟xid,那么为什么要首先创建它呢? - Greedy Coder
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Brandon
2个回答

15
连接不会创建事务,但如果会话还没有当前开放的事务,则发出select * from pg_locks会隐式地创建一个事务。 这符合您在问题中引用的规则:所有语句在Postgres中都在事务中运行,无论是显式的还是隐式的
查询select * from pg_locks不能作为中立观察者,因为它需要使用一个事务和对pg_locks的锁定。因此,此选择将始终报告至少两个条目,如下例所示:

我忘记了我实际上正在运行pg_locks的查询。现在清楚了,但是为什么postgres首先创建它,这个设计决策背后有什么特别的原因? - Greedy Coder
1
@GreedyCoder:在查询涉及的对象上获取AccessShareLock,以阻止它们在使用期间被其他会话修改或删除。 - Daniel Vérité

7
只要您查询pg_locks,实际上就会运行查询并启动事务。例如,它需要在pg_locks上获取AccessShareLock。这就是为什么会分配virtualxid的原因。
但虚拟事务ID与实际事务ID相比更加"自由"。Virtualxid仅适用于后端(它由后端编号加上一些顺序编号组成)。而实际事务ID是系统范围内的32位数字,因此当计数器归零时,存在包裹问题的可能性。必须采取特殊措施以防止系统在那一刻崩溃,因此PostgreSQL不愿意在实际需要之前分配实际事务ID。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接