避免在多台机器中重复增加 SERIAL 列
Posted
技术标签:
【中文标题】避免在多台机器中重复增加 SERIAL 列【英文标题】:Avoid duplicate increment in SERIAL column in mutiple machines 【发布时间】:2014-04-20 14:47:15 【问题描述】:现在我在单台机器上安装了 Postgres 并创建了一个带有 serial
列的表。每当插入新行时,此列就会自动增加。如果我在另一台机器上安装 Postgres 以进行分布式计算并使用serial
列创建同一个表,serial
列从 1 开始?或者我可以为列设置最小值(第一台机器的最大值+1)?
【问题讨论】:
【参考方案1】:默认情况下,SERIAL
创建一个以 1 开头的 SEQUENCE
。
如果需要,您可以修改序列,使每台机器都有一个不同的起始值,并且所有序列在创建表后都有一个偏移量。例如,ALTER SEQUENCE the_sequence_name START WITH 2 INCREMENT BY 10
。给每台机器设置不同的START WITH
值并确保它们都具有相同 INCREMENT BY
。这样可以保证每台机器都获得唯一的 ID。
如果您这样做,您可能希望使用bigint
键列,并分配像INCREMENT BY 1000
这样的大偏移量。这样一来,当您必须添加机器 #11 时,您就不会感到痛苦。
另一种选择是使用uuid
主键。
【讨论】:
考虑我对START
与RESTART
的回答。【参考方案2】:
请注意,ALTER SEQUENCE
中的 START
子句仅设置默认起始值。它确实不会改变序列的当前值,这是一种常见的误解。
如果您在CREATE SEQUENCE
语句中使用该子句,则该序列将使用START
值进行初始化,并按预期运行:第一次调用nextval()
将在此处返回7
:
CREATE SEQUENCE foo_seq START WITH 7 INCREMENT BY 16;
但是,如果您运行ALTER SEQUENCE
,则序列已经初始化为其他值(默认为 1),您需要添加一个 RESTART
子句来实际重置序列:
ALTER SEQUENCE foo_seq START WITH 7 INCREMENT BY 16 <b>RESTART</b>;
Per documentation:
重启
可选子句
RESTART [ WITH restart ]
更改序列的当前值。这相当于调用setval
带有is_called = false
的函数:将返回指定的值 下次拨打nextval
。写RESTART
没有重启值是 相当于提供CREATE
记录的起始值SEQUENCE
或最后由ALTER SEQUENCE START WITH
设置。
当您更改为 serial
列隐式创建的序列时,这就是您所需要的。
这也是您真正需要的问题:
ALTER SEQUENCE foo_seq <b>RESTART WITH max_of_other_tbl</b>;
SQL FIDDLE demonstrating the variants.
【讨论】:
我会选择 2 的幂作为增量。这将导致(假设的)环绕仅对本地安装产生影响,而不是与对等方发生冲突。 @wildplasser:有效的考虑。不花钱,有收获。我相应地调整了我的例子。 我还没有体验过我的第一个环绕式连续剧。但我不希望它成为一个多安装问题(还记得 Oracle 高水印的事情......?)以上是关于避免在多台机器中重复增加 SERIAL 列的主要内容,如果未能解决你的问题,请参考以下文章
如何使用Tomcat从属性文件中检索数据库属性以便在多台机器上工作[重复]
使用 Not exists SQL ORACLE 避免列重复