Postgres 9.5:作为外键重新引用的行的非零xmax

时间:2016-04-16 13:01:57

标签: postgresql foreign-key-relationship

根据http://www.postgresql.org/docs/current/static/ddl-system-columns.html

  

xmax - 删除事务的标识(事务ID),或   对于未删除的行版本为零。这个专栏可以   在可见的行版本中非零。那通常表明了   删除尚未提交的交易或已尝试的交易   删除被回滚。

但是如果一行被另一行引用为外键,则xmax也具有非零值:

drop table if exists demo;
create table demo
(
    id bigint primary key not null,
    pid bigint,
    constraint demo_pid_fk
        foreign key (pid)
    references demo (id)
);

insert into demo(id, pid) values(1, NULL); 
insert into demo(id, pid) values(2, 1); 
insert into demo(id, pid) values(3, 3); 
select xmin, xmax, * from demo;
 xmin | xmax | id | pid 
------+------+----+-----
 1074 | 1075 |  1 |    
 1075 |    0 |  2 |   1
 1076 | 1076 |  3 |   3
(3 rows)

insert into demo(id, pid) values(4, 1); 
select xmin, xmax, * from demo;
 xmin | xmax | id | pid 
------+------+----+-----
 1074 | 1077 |  1 |    
 1075 |    0 |  2 |   1
 1076 | 1076 |  3 |   3
 1077 |    0 |  4 |   1
(4 rows)

在上面的示例中,似乎xmax设置为将该行作为外键引用的最后一个事务的id。为什么会这样? Postgres如何知道该行仍然存在?

1 个答案:

答案 0 :(得分:2)

Bruce Momkian在MVCC, unveiling xmin and xmax workslides上进行了一次演讲,使用Xmax和#34搜索"行锁;)。

长话短说:xmax也用于 - 在文档中没有很好地涵盖 - 用于行锁,在这种特定情况下CASCADE用于确保其他事务远离修改引用的元组(所以txid_current()会等待(例如),除非xmax大于插入的VACUUM FULL demo。实际上,表格中的非零xmax不会被{{1}}使用和清理。