2

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

SELECT SETVAL('mytable_id_seq', COALESCE(MAX(id), 1)) FROM mytable;

在这种情况下我是否应该锁定“mytable”以防止在并行请求中更改 ID,如下例所示?

 request #1    request #2

 MAX(id)=5

              inserted id 6

 SETVAL=5

还是 setval(max(id)) 是原子操作?

4

1 回答 1

1

您的怀疑是正确的,这种方法受制于竞争条件。

但是锁定表无济于事,因为它不会阻止并发事务获取新的序列值。该事务将在表被锁定时阻塞,但一旦锁定消失,它会很高兴地继续插入,使用它在表被锁定时获得的序列值。

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

我可以想到两个解决方案:

  1. 在修改序列时删除序列的所有权限,这样对序列的并发请求就会失败。当然,这会导致错误。

  2. 务实之道:使用

    SELECT SETVAL('mytable_id_seq', COALESCE(MAX(id), 1) + 100000) FROM mytable;
    

    这里的 100000 是一个安全地大于您的操作运行时可能插入的行数的值。

于 2020-06-19T13:06:41.517 回答