Postgresql 关于“的几个问题”;选择以更新";?

Postgresql 关于“的几个问题”;选择以更新";?,postgresql,Postgresql,下面是使用libpq.so的伪代码;但它不像我想的那样 transaction begin re1 = [select ics_time from table1 where c1=c11, c2=c22, c3=c33, c4=c44 for update]; if(re1 satisfies the condition) { re2 = [select id where c1=c11, c2=c22, c3=c33, c4=c44 for update]; delete fro

下面是使用libpq.so的伪代码;但它不像我想的那样

transaction begin

re1 = [select ics_time from table1 where c1=c11, c2=c22, c3=c33, c4=c44 for update];

if(re1 satisfies the condition)
{
   re2 = [select id where c1=c11, c2=c22, c3=c33, c4=c44 for update];
   delete from table1 where id = re2;
   delete from table2 where id = re2;
   delete from table3 where id = re3;
   insert a new record into table1,table2,table3 with the c1,c2,c3,c4 as primary keys;
]
commit or rollback
请注意,c1、c2、c3、c4都被设置为数据库中的主键,因此数据库中只有一行包含这些键

让我困惑的是:

  • 有两个“选择更新”将锁定同一行。在里面 在这段代码中,第二条SQL语句是否等待独占锁 被第一条语句阻止了吗?但实际情况是, 不会发生
  • 发生了出乎我意料的事。在日志中,我看到一个大的 重复插入错误数。在我看来,“选择 for update“使用唯一for键锁定行,两个进程 连续进行。插入操作在删除之后进行。这些怎么可能 重复插入发生了吗?“选择更新”是否添加了一个 对行的独占锁定,这将阻止 要锁定同一行吗

  • 关于第一点:锁不是由语句持有的,而是由周围的事务持有的。您的伪代码似乎对一个事务使用一个连接,而该事务又使用多个语句。因此,第二个
    选择更新
    不会被第一个阻止。请阅读以下内容:

    […]更新或删除行时,会自动获取特定行上的排他行级别锁。锁一直保持到事务提交或回滚,就像表级锁一样。行级锁不影响数据查询;它们只阻止同一行的写入程序

    否则,如果一个事务可以如此轻松地阻止自己,那将非常有趣


    关于你的第二点:我不能回答这个问题,因为a)你的伪代码对于这个问题是伪代码,b)我不理解你所说的“进程”和确切的用例是什么意思

    你的伪代码毫无意义。您没有筛选SELECT中的任何行以进行更新。您说主键是(c1、c2、c3、c4)在所讨论的表上,但随后被某个新列“id”删除。尝试提供实际显示问题的SQL。id是链接表1、表2和表3的外键,id是从第二个“选择更新”中选择的。这有意义吗?@RichardHuxtonno,这有什么意义?您没有在第二个“选择更新”中选择“id”,也没有在以后插入它。显示一些重现问题的实际SQL,这样人们就能明白你的意思。对不起,我在伪代码中犯了一些错误,现在已经更正了,这有意义吗?@RichardHuxtonNo-仍然有明显的错误。我运行了几个进程或线程,其中包含上面的伪代码,因此,多个进程可以被看作是连接到数据库的多个用户。这有什么意义吗@对不起,我在上面的伪代码中犯了错误,现在已经更正了,你能看清楚吗@A.H。