【发布时间】:2013-03-31 15:26:58
【问题描述】:
这是使用 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 键锁定行,两个过程 依次进行。插入操作在删除之后进行。这些怎么可能 出现重复插入? “选择更新”是否添加了一个 该行的排他锁,它阻塞所有其他进程 想要锁定同一行?
【问题讨论】:
-
你的伪代码没有意义。您没有过滤 SELECT FOR UPDATE 中的任何行。您说有问题的表上的主键是(c1,c2,c3,c4),但随后被一些新列“id”删除。尝试提供实际显示问题的实际 SQL。
-
id是连接table1、table2和table3的外键,id是从第二个“select for update”中选择的。这有什么意义吗?@RichardHuxton
-
不,这怎么可能?您没有在第二个“选择更新”中选择“id”,以后也没有插入它。显示一些重现问题的实际 SQL,然后人们就会明白你的意思。
-
对不起,我在伪代码中犯了一些错误,现在更正了,有意义吗?@RichardHuxton
-
否 - 仍然存在明显错误。请只发布显示问题的真实 SQL。
标签: postgresql