提交事务

时间:2015-11-26 16:43:34

标签: sql postgresql transactions commit

假设我有一个表格,我希望使用serial作为主键来请求客户端的更改。客户将询问"在关键X"之后给我更改。在不使用SERIALIZABLE隔离级别或锁定的情况下,这很容易出现竞争条件。

事务A可以先启动,然后执行写操作,然后花费很长时间来提交。同时事务B将在A提交之前启动并提交。来自B的写入将获得比来自A的写入更高的主键。如果客户端现在要求更改,则它将错过来自A的仍未提交的写入,并记下最新的最高主键。所以即使在A提交之后,客户端也永远不会看到这种变化,因为它的密钥低于客户端已经获得的变化。

是否有可能在提交时以原子方式确定serial(或来自计数器的类似值)的值,以便我们保证在提交时它将高于所有其他值,并且低于所有其他值它会在之后发生吗?如果不是解决这个问题的最佳方法是什么?

1 个答案:

答案 0 :(得分:7)

Postgres 9.5 引入了与此问题相关的新功能: 提交时间戳

您只需要在postgresql.conf中激活track_commit_timestamp(并重新启动!)即可开始跟踪提交时间戳。然后你可以查询:

SELECT * FROM tbl
WHERE  pg_xact_commit_timestamp(xmin) >= '2015-11-26 18:00:00+01';

阅读Postgres Wiki中的"Commit timestamp tracking"章节 相关utility functions in the manual

函数波动率仅为VOLATILE,因为事务ID(xid)可以根据定义进行包装。所以无法在其上创建功能索引 您可以在有限的时间范围内为函数包装器伪造IMMUTABLE波动率,但您需要了解其含义。相关案例有更多解释:

对于许多只对提交顺序感兴趣的用例(而不是绝对时间),使用xmin强制转换为bigint&#34可能更有效率;直接" (xmin::text::bigint)而不是提交时间戳。 (xid是内部的无符号整数,上半部分不适合签名的integer。)同样,请注意由于可能的xid环绕而导致的限制。

出于同样的原因,提交时间戳 无法无限期保留 。对于中小型数据库,xid环绕几乎没有发生 - 但最终如果集群的生存时间足够长。有关详细信息,请阅读手册中的"Preventing Transaction ID Wraparound Failures"章节。