Jul*_*ien 8 postgresql locking postgresql-9.6
PostgreSQL 9.6 的情况:
SELECT id FROM A FOR UPDATE;
阻塞UPDATE B SET x=y;
直到 A 上的锁被释放。
我认为这是因为引用的值可能会改变。我怎样才能在不删除外键约束的情况下避免第一个语句阻塞第二个语句的执行?
如果我放弃外键约束,我应该期待什么坏事?在出现这个问题的实际数据库中,如果表 B 从 A 删除后还有剩余行,这不会是一个重大问题。我们也从不更新主键。
用代码编辑:
-- Setup
create table a (id int primary key);
create table b (id int primary key references a (id) on update cascade on delete cascade, x varchar);
insert into a values (1), (2);
insert into b values (1, null), (2, null);
-- Left
begin;
select 1 from a for update;
/* Keep the transaction open */
-- Right
begin;
update b set x = 'abc' where id = 1;
update b set x = 'xyz'; /* It blocks here /*
Run Code Online (Sandbox Code Playgroud)
ype*_*eᵀᴹ 10
我们也永远不会更新主键。
在这种情况下,我认为您可以使用FOR NO KEY UPDATE
代替FOR UPDATE
. 这是一个较弱的锁,如 Postgres docs about Explicit Locking 中所述:
FOR NO KEY UPDATE
行为与 类似
FOR UPDATE
,不同之处在于获取的锁较弱:此锁不会阻止SELECT FOR KEY SHARE
尝试获取相同行上的锁的命令。这种锁定模式也被任何UPDATE
没有获得FOR UPDATE
锁定的人获得。
测试:
-- Setup
create table a (id int primary key,
x varchar);
create table b (id int primary key
references a (id) on update cascade on delete cascade,
x varchar);
insert into a values (1), (2);
insert into b values (1, null), (2, null);
-- Left
begin;
select 1 from a for no key update;
/* Keep the transaction open */
-- Right
begin;
update b set x = 'abc' where id = 1;
update b set x = 'xyz'; -- doesn't block
-- Left
update a set x = 'left' where id = 1;
commit ;
-- Right
commit ;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
9593 次 |
最近记录: |