关于“选择更新”的一些问题?

时间:2013-03-31 03:23:19

标签: 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 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都被设置为数据库中的主键,因此数据库中只有一行包含这些键。

令我困惑的是:

  1. 有两个“select for update”将锁定同一行。在 这段代码,第二个SQL语句是否等待独占锁 被第一个声明阻止了吗?但是,实际情况是这样的 不会发生。
  2. 有些事情发生在我的期望之外。在日志中,我看到一个大的 重复插入错误的数量。在我看来,“选择 for update“锁定具有唯一键的行,两个进程 连续去。删除后进行插入操作。怎么可以这些 重复插入发生?不是“选择更新”添加 对行的独占锁定,阻止所有其他进程 想锁定同一行吗?

1 个答案:

答案 0 :(得分:4)

关于你的第一点:声明不持有锁,周围的交易持有锁。您的伪代码似乎与一个事务使用一个连接,而后者又使用多个语句。所以第二个SELECT FOR UPDATE没有被第一个阻止。请阅读docs about locking

  

[...]更新或删除行时,将自动获取特定行上的独占行级锁定。锁定一直持续到事务提交或回滚,就像表级锁一样。行级锁不会影响数据查询;他们只阻止作者到同一行。

否则,如果交易可以轻易阻止自己,那将非常有趣。

关于你的第二点:我不能回答这个问题因为a)你的伪代码对于这个问题是伪的,而b)我不明白你的意思是“进程”和确切的用例。