提交事务时自动设置 SERIAL 值
Atomically set SERIAL value when committing transaction
假设我有一个 table,我想在其中使用 serial
作为主键来请求客户端进行更改。客户会问"give me the changes after key X"。如果不使用 SERIALIZABLE
隔离级别或锁定,这很容易出现竞争条件。
事务A可以先启动,然后写,然后花很长时间提交。同时,事务 B 将在 A 提交之前启动并提交。来自 B 的写入将获得比来自 A 的写入更高的主键。如果客户端现在请求更改,它将错过来自 A 的尚未提交的写入,并记下最新的最高主键。所以即使在 A 提交之后,客户端也永远不会看到该更改,因为它的密钥低于客户端已经获得的更改。
是否可以在提交时自动确定 serial
(或来自计数器的类似值)的值,以便我们保证在提交时它会高于所有其他值,而低于比所有这一切都将在它之后被承诺?如果不是,解决此问题的最佳方法是什么?
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
波动性,但您需要了解其中的含义。相关案例更多解释:
- Does PostgreSQL support "accent insensitive" collations?
对于许多只对提交顺序(而不是绝对时间)感兴趣的用例(比如你的?),使用 xmin
转换为 bigint
可能更有效”直接”(xmin::text::bigint
)而不是提交时间戳。 (xid
在内部是一个无符号整数,上半部分不适合带符号的 integer
。)再次注意由于可能的 xid 环绕而造成的限制。
出于同样的原因,提交时间戳不会无限期保留。对于中小型数据库,xid
环绕几乎不会发生——但如果集群运行时间足够长,它最终会发生。阅读手册中的 "Preventing Transaction ID Wraparound Failures" 章节了解详情。
假设我有一个 table,我想在其中使用 serial
作为主键来请求客户端进行更改。客户会问"give me the changes after key X"。如果不使用 SERIALIZABLE
隔离级别或锁定,这很容易出现竞争条件。
事务A可以先启动,然后写,然后花很长时间提交。同时,事务 B 将在 A 提交之前启动并提交。来自 B 的写入将获得比来自 A 的写入更高的主键。如果客户端现在请求更改,它将错过来自 A 的尚未提交的写入,并记下最新的最高主键。所以即使在 A 提交之后,客户端也永远不会看到该更改,因为它的密钥低于客户端已经获得的更改。
是否可以在提交时自动确定 serial
(或来自计数器的类似值)的值,以便我们保证在提交时它会高于所有其他值,而低于比所有这一切都将在它之后被承诺?如果不是,解决此问题的最佳方法是什么?
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
波动性,但您需要了解其中的含义。相关案例更多解释:
- Does PostgreSQL support "accent insensitive" collations?
对于许多只对提交顺序(而不是绝对时间)感兴趣的用例(比如你的?),使用 xmin
转换为 bigint
可能更有效”直接”(xmin::text::bigint
)而不是提交时间戳。 (xid
在内部是一个无符号整数,上半部分不适合带符号的 integer
。)再次注意由于可能的 xid 环绕而造成的限制。
出于同样的原因,提交时间戳不会无限期保留。对于中小型数据库,xid
环绕几乎不会发生——但如果集群运行时间足够长,它最终会发生。阅读手册中的 "Preventing Transaction ID Wraparound Failures" 章节了解详情。