在使用max ID函数调用sequence的setval时,是否应该锁定PostgreSQL表?

在使用max ID函数调用sequence的setval时,是否应该锁定PostgreSQL表?,postgresql,transactions,locking,database-sequence,Postgresql,Transactions,Locking,Database Sequence,我有以下SQL脚本,它设置与ID列的最大值对应的序列值: SELECT SETVAL('mytable_id_seq', COALESCE(MAX(id), 1)) FROM mytable; 在这种情况下,我是否应该锁定“mytable”以防止在并行请求中更改ID,例如下面的示例 请求#1请求#2 最大值(id)=5 插入id 6 SETVAL=5 或者setval(max(id))是一个原子操作?您的怀疑是对的,这种方法受竞争条件的影响 但是锁定表不会有帮助,因为它不会阻止并发事务获取新

我有以下SQL脚本,它设置与ID列的最大值对应的序列值:

SELECT SETVAL('mytable_id_seq', COALESCE(MAX(id), 1)) FROM mytable;
在这种情况下,我是否应该锁定“mytable”以防止在并行请求中更改ID,例如下面的示例

请求#1请求#2
最大值(id)=5
插入id 6
SETVAL=5

或者setval(max(id))是一个原子操作?

您的怀疑是对的,这种方法受竞争条件的影响

但是锁定表不会有帮助,因为它不会阻止并发事务获取新的序列值。当表被锁定时,该事务将被阻塞,但一旦锁消失,它将使用在表被锁定时获得的序列值继续插入

如果可以锁定序列,这可能是一个解决方案,但不可能锁定序列

我可以想出两种解决办法:

  • 在修改序列时删除该序列上的所有权限,以便对该序列的并发请求将失败。当然,这会导致错误

  • 语用方式:使用

    SELECT SETVAL('mytable_id_seq', COALESCE(MAX(id), 1) + 100000) FROM mytable;
    
    这里100000是一个安全的值,它大于操作运行时可能插入的行数