Kub*_*uba 5 postgresql deadlock database-deadlocks
我想更好地理解postgres中的锁定机制.
假设树可以有苹果(通过苹果桌上的外键).似乎在选择树时进行更新锁定是在苹果上获得的.但是,即使其他人已经锁定了这个苹果,操作也不会被阻止.
为什么会这样?
ps请不要建议删除"选择更新".
Transaction 1 Transaction 2
BEGIN .
update apple; .
. BEGIN
. select tree for update;
. update apple;
. --halts because of the other transaction locking an apple
update apple; .
-- deadlock .
COMMIT
--transaction succeeds
Run Code Online (Sandbox Code Playgroud)
如果你想在你的postgres中尝试 - 这是一个你可以复制/粘贴的代码.
我有一个以下的数据库架构
CREATE TABLE trees (
id integer primary key
);
create table apples (
id integer primary key,
tree_id integer references trees(id)
);
Run Code Online (Sandbox Code Playgroud)
而且非常简单的数据
insert into trees values(1);
insert into apples values(1,1);
Run Code Online (Sandbox Code Playgroud)
有两个简单的交易.一个是更新苹果,第二个是锁定树并更新苹果.
BEGIN;
UPDATE apples SET id = id WHERE id = 1;
-- run second transaction in paralell
UPDATE apples SET id = id WHERE id = 1;
COMMIT;
BEGIN;
SELECT id FROM trees WHERE id = 1 FOR UPDATE;
UPDATE apples SET id = id WHERE id = 1;
COMMIT;
Run Code Online (Sandbox Code Playgroud)
当我运行它们时 - 第一次事务的第二次更新发生死锁.
ERROR: deadlock detected
DETAIL: Process 81122 waits for ShareLock on transaction 227154; blocked by process 81100.
Process 81100 waits for ShareLock on transaction 227153; blocked by process 81122.
CONTEXT: SQL statement "SELECT 1 FROM ONLY "public"."trees" x WHERE "id" OPERATOR(pg_catalog.=) $1 FOR SHARE OF x"
Run Code Online (Sandbox Code Playgroud)
只是一个疯狂的猜测:你遇到了与实现细节相关的问题......
具体来说,您的select tree for update
语句获取树上的独占锁.这些update apples
陈述获得了对相关苹果的独家锁定.
当你在apple上运行更新时,Postgres的每行相关的外键触发会触发,以确保tree_id
存在.我不记得他们的精确名字在我的头顶,但它们在目录中,文档中有一些零碎的部分明确地或隐含地引用它们,例如:
create constraint trigger ... on ... from ...
Run Code Online (Sandbox Code Playgroud)
http://www.postgresql.org/docs/current/static/sql-createtrigger.html
无论如何,这些触发器将运行相当于以下内容:
select exists (select 1 from trees where id = 1);
Run Code Online (Sandbox Code Playgroud)
其中存在的问题是:由于select for update
使得它等待事务2释放对树的锁定以便最终确定其关于apple的更新语句的独占访问,但是事务2正在等待事务1完成以获得锁定在苹果上,以便开始关于苹果的更新声明.
结果,Postgres陷入僵局.
归档时间: |
|
查看次数: |
6030 次 |
最近记录: |