postgreSQL 如何标记冻结的行?

How posgreSQL marks frozen rows?

我正在研究VACUUM命令。特别是它如何解决环绕问题。

基本上每笔交易都有一个交易ID。每行都关联了具有 updated/inserted 它的最后一个事务的事务 ID。与特定行关联的事务 ID 可以在系统列 xmin 中看到。具有相同事务的行 updated/inserted 将具有相同的事务 ID (XID)。

这些 ID 控制该行对其他并发事务的可见性。 ID为50的事务,可以看到transactionID < 50的所有行。

交易ID可以有40亿以上的值(32位)。问题是,当我们达到这个值时,事务 ID 需要重新启动,这意味着对于这个事务,所有行突然都不可见(它具有最低的事务 ID),即使这些行是过去添加的。这称为环绕问题。

我知道 vacuum 解决了将旧行标记为冻结的问题。如何查看已冻结的行? xmin会有具体值吗?

此信息存储在 tuple header (HeapTupleHeaderData) 的 t_infomask 中。请参阅 src/include/access/htup_details.h 中的以下定义:

/*
 * information stored in t_infomask:
 */
[...]
#define HEAP_XMIN_COMMITTED     0x0100  /* t_xmin committed */
#define HEAP_XMIN_INVALID       0x0200  /* t_xmin invalid/aborted */
#define HEAP_XMIN_FROZEN        (HEAP_XMIN_COMMITTED|HEAP_XMIN_INVALID)

您无法通过 SQL 直接访问该信息,但如果您使用 pageinspect 扩展,则可以使用 heap_page_itemsheap_tuple_infomask_flags 函数来读取该信息来自原始的 8kB 页面。