【问题标题】:Strange cleanup behaviour with FOR UPDATEFOR UPDATE 的奇怪清理行为
【发布时间】:2014-06-24 08:49:08
【问题描述】:

我想知道即使在子查询中使用了 FOR UPDATE 子句,在 UPDATE 操作之后是否不应该将 xmax 值设置为零?

我已经创建了测试表:

CREATE TABLE def.dummy
(
  id serial NOT NULL,
  nazwa text,
  CONSTRAINT pk_dummy PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);

并插入一些值:

INSERT INTO def.dummy(
            nazwa)
    VALUES ('1'),('2'),('3');

现在当我尝试使用子查询进行更新时:

UPDATE def.dummy AS sp
SET nazwa = 'changed' FROM
(SELECT id, nazwa, xmax, xmin
 FROM def.dummy
          WHERE id=1
AND xmax = 0
LIMIT 1 FOR UPDATE) AS get_set
WHERE get_set.id = sp.id;
RETURNING sp.*;

提交事务后,xmax 值不会重置为 0,而是保持为:

这是正确的行为吗?如果是,为什么运行后xmax不设置为零?

【问题讨论】:

    标签: sql-update postgresql-9.3 mvcc


    【解决方案1】:

    是的,这种行为是正确的。 Xmax 也用于储物柜,不仅是更新程序,而且当 t_infomask 中设置 LOCK 位时,由值的读取者确保它忽略非零值(有关 t_infomask 中位的值,请参阅src/include/access/htup_details.h )。虽然您无法从常规 SQL 界面访问 t_infomask,但请参阅 pageinspect 扩展名,它可以让您访问它。

    请注意,元组也可以通过外键检查来锁定,因此不仅仅是 FOR UPDATE 会导致非零值出现在 Xmax 中。

    【讨论】:

    • 感谢您的回答。你知道我在哪里可以找到这些信息吗?例如,在文档中找不到有关外键检查的任何信息。
    • 我认为我们不会记录这种事情;将来每当我们想更改底层表示时,它都会成为一个问题,因为如果我们记录它,人们将变得依赖于一种特定的方式来做这件事。当然,您可以随时阅读源代码,对于 PostgreSQL,源代码有很好的文档记录。
    猜你喜欢
    • 1970-01-01
    • 2011-02-02
    • 2011-07-28
    • 1970-01-01
    • 2019-02-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多