我有以下表格:
Table "public.product"
Column | Type | Modifiers
--------+---------+------------------------------------------------------
id | integer | not null default nextval('product_id_seq'::regclass)
name | text | not null
Indexes:
"product_pkey" PRIMARY KEY, btree (id)
Referenced by:
TABLE "stock" CONSTRAINT "stock_product_id_fkey" FOREIGN KEY (product_id) REFERENCES product(id)
此表有2条记录: -
postgres=# select xmin, xmax, cmin, cmax, * from product;
xmin | xmax | cmin | cmax | id | name
---------+---------+------+------+----+---------
3126848 | 3126856 | 0 | 0 | 1 | Parle-G
3126849 | 3126858 | 0 | 0 | 2 | Pepsi
(2 rows)
我有以下与xmax和cmin列有关的问题: -
根据postgres文档,xmax存储删除此行的事务的id。但由于我的行尚未删除,为什么它包含非零值。
Postgres docs说cmin包含事务中的语句序列号,它创建了这一行。根据SQL标准,每个语句本身都是一个事务,因此以这种方式,它必须包含cmin列的非零数字。
请纠正我,我错了。提前谢谢。
答案 0 :(得分:5)
我先回答你的第二个问题,因为这很简单:
cmin
从零开始计数,因此cmin
为零意味着这是事务中的第一个语句。如果您的所有交易都包含一个语句,那么您可以期望cmin
始终为零。
关于xmax
:
除了存储删除该行的事务的编号外,此系统列还用于存储行锁。它们存储在行本身而不是共享内存中,以避免锁表溢出。
行锁以两种不同的方式存储:
如果只有一个交易持有一行锁,则交易号存储在xmax
。
如果一个行上有多个(共享)锁,则会创建一个 multixact 结构,其编号存储在xmax
中。
xmax
的不同用法之间没有冲突,因为数据库有其他信息:
表格行中的其他标记(系统列不可见)消除了xmax
的含义歧义。
提交日志存储交易是否已提交。只有已提交事务删除的行才会被删除。
总结一下,如果你在xmax
中看到一个非零值,那可能意味着四件事:
该行已被删除或更新,您的查询正在使用比修改事务更早的快照运行。
该行已被回滚的事务删除或更新。
该行已锁定或已在过去的某个时间点被锁定,您会看到锁定事务的事务ID。
如上所述,但您会看到 multixact 值。您可以使用函数pg_get_multixact_members
查看哪些交易属于它。
您可能有兴趣阅读my blog post,我会更详细地探讨这个问题。