假设从创建的角度来看,在 Postgres 中通过自动递增 PK 进行排序是否会按时间顺序对记录进行排序?我有一个多对多的关系,除了关系本身和某种形式的创建顺序之外,我不需要跟踪其他任何东西。我正在尝试决定是否需要为此合并时间戳列,或者是否可以出于相同目的重新利用现有的自动递增 PK 列。
假设从创建的角度来看,在 Postgres 中通过自动递增 PK 进行排序是否会按时间顺序对记录进行排序?我有一个多对多的关系,除了关系本身和某种形式的创建顺序之外,我不需要跟踪其他任何东西。我正在尝试决定是否需要为此合并时间戳列,或者是否可以出于相同目的重新利用现有的自动递增 PK 列。
假设“自动递增”是指 Postgres
SERIAL
伪类型,简短的回答是“不总是”。SERIAL
CACHE
列是使用标准 SQL 序列实现的,如果参数设置为大于 1,则在多个并发会话使用时可能会生成乱序值。手册指出:将 value保留
CACHE
为 1 可能会损害高并发环境中的性能,因此您必须选择对您更重要的内容。在我看来,尝试重新
SERIAL
用于跟踪记录的创建顺序并不是一个好主意,因为它可能会产生维护问题:因为序列的唯一承诺是为每个请求提供一些唯一的递增值nextval
,这取决于它在一个请求下的行为当情况发生变化时,情况可能会导致您的应用程序出现不可预测的行为,例如,在未来的 Postgres 版本中修改了序列实现细节,或者工作负载的变化需要您增加CACHE
设置。使用适当的时间戳进行排序既安全又语义清晰。你说的时间顺序是什么意思?
如果有一个事务 1 在事务 2 之前开始,但在事务 2 之后结束,那么第一个事务是事务 1 还是事务 2?
如果您使用
SERIALIZABLE
事务隔离级别,则它保证事务有一个总顺序:也就是说,事务有一些串行(非并行)顺序,这些顺序会给出与实际运行的事务相同的结果生活平行系统。最有可能的是,PostgreSQL 序列不会给出与可序列化总顺序完全相同的值顺序。您可以通过创建自己的序列来解决此问题:创建一个表,其中一行包含一个整数列,并更新该行。但是,如果这样做,您的事务的并行性就会受到影响。它甚至可能以导致某些交易失败的方式受到影响。
正如评论所提出的,一种解决方案是时间戳。但是,时间戳顺序不一定与给出相同结果的串行顺序相同。
(附带说明一下,您应该为所有情况下的失败事务做好准备。死锁会导致失败的事务。
SERIALIZABLE
隔离级别会导致更多的失败事务。正确的方法是指数退避和重试。)