Sql 提交事务时自动设置序列值
假设我有一个表,其中我想使用Sql 提交事务时自动设置序列值,sql,postgresql,transactions,commit,Sql,Postgresql,Transactions,Commit,假设我有一个表,其中我想使用串行作为主键,请求客户机进行更改。客户会问“在X键后给我更改”。如果不使用SERIALIZABLE隔离级别或锁定,很容易出现争用情况 事务A可以先启动并进行写操作,然后花很长时间提交。同时,事务B将在A提交之前启动并提交。来自B的写入将获得比来自a的写入更高的主键。如果客户端现在请求更改,它将错过来自a的尚未提交的写入,并注意最新的最高主键。因此,即使在提交之后,客户机也不会看到该更改,因为其密钥低于客户机已经得到的更改 是否可以在提交时以原子方式确定串行(或计数器中
串行
作为主键,请求客户机进行更改。客户会问“在X键后给我更改”。如果不使用SERIALIZABLE
隔离级别或锁定,很容易出现争用情况
事务A可以先启动并进行写操作,然后花很长时间提交。同时,事务B将在A提交之前启动并提交。来自B的写入将获得比来自a的写入更高的主键。如果客户端现在请求更改,它将错过来自a的尚未提交的写入,并注意最新的最高主键。因此,即使在提交之后,客户机也不会看到该更改,因为其密钥低于客户机已经得到的更改
是否可以在提交时以原子方式确定
串行
(或计数器中的类似项)的值,从而保证提交时该值高于所有其他值,而低于提交后将提交的所有值?如果不是,解决此问题的最佳方法是什么?Postgres9.5引入了与此问题相关的新功能:提交时间戳
您只需在postgresql.conf
中激活(并重新启动!)即可开始跟踪提交时间戳。然后您可以查询:
SELECT * FROM tbl
WHERE pg_xact_commit_timestamp(xmin) >= '2015-11-26 18:00:00+01';
阅读Postgres Wiki中的章节。相关的 函数波动性只是
波动性
,因为事务ID(xid
)可以根据定义进行包装。因此,您无法在其上创建功能索引。您可以在有限的时间范围内为应用程序在函数包装中伪造
不可变的
波动性,但您需要注意其含义。有更多解释的相关案例:
xmin
直接转换为bigint
(xmin::text::bigint
)而不是提交时间戳可能更有效。(xid
在内部是一个无符号整数,上半部分不适合有符号的integer
)同样,请注意可能的xid环绕所带来的限制
出于同样的原因,提交时间戳不会无限期保留。对于中小型数据库,
xid
wrapparound几乎从未发生过,但如果集群的生存时间足够长,它最终会发生。有关详细信息,请阅读手册中的章节。很有趣。如果我添加“ORDER BY pg_xact_commit_timestamp(xmin)”,执行这样的查询是否也会很有效,就像我使用索引列一样?@NotNull:函数本身有索引支持来检索时间戳,但恐怕您无法对结果创建函数索引。我在上面又加了一些。谢谢@ErwinBrandstetter让我们了解这一点xmin
是一个不专门属于表的系统列。我不会为这个值创建一个索引,因为它是全球性的,并且可以增长得非常巨大,但这是我的观点。让我们看看欧文对此有何评论。不管怎样,我想可能不可能创建这样的索引。@ConsiderMe什么?每个表都有xmin
,它是一个隐藏的系统列,但并不是所有表都共享它。您无法真正为其编制索引的原因是xid wraparound,与它的全局性无关。一般的解决方案可能是在修改需要以这种方式查询的表的事务中使用建议锁(在标识每个客户端感兴趣的所有行的ID上),为了保护主键不受我所描述的竞争条件的影响,如果没有提交时间戳来提供一致的全局排序,这在并发插入的情况下实际上是很难做到的。PostgreSQL通过跟踪最旧和最新的当前xid,以及其中提交的位图,在xid级别对快照执行此操作。我不认为你真的可以把它转换成一个序列。可能是重复的