比方说,我有一个交易表和transaction_summary表。我创建了以下触发器以更新transaction_summary表。锁定在Postgres功能
CREATE OR REPLACE FUNCTION doSomeThing() RETURNS TRIGGER AS
$BODY$
DECLARE
rec_cnt bigint;
BEGIN
-- lock rows which have to be updated
SELECT count(1) from (SELECT 1 FROM transaction_summary WHERE receiver = new.receiver FOR UPDATE) r INTO rec_cnt ;
IF rec_cnt = 0
THEN
-- if there are no rows then create new entry in summary table
-- lock whole table
LOCK TABLE "transaction_summary" IN ACCESS EXCLUSIVE MODE;
INSERT INTO transaction_summary(...) VALUES (...);
ELSE
UPDATE transaction_summary SET ... WHERE receiver = new.receiver;
END IF;
SELECT count(1) from (SELECT 1 FROM transaction_summary WHERE sender = new.sender FOR UPDATE) r INTO rec_cnt ;
IF rec_cnt = 0
THEN
LOCK TABLE "transaction_summary" IN ACCESS EXCLUSIVE MODE;
INSERT INTO transaction_summary(...) VALUES (...);
ELSE
UPDATE transaction_summary SET ... WHERE sender = new.sender;
END IF;
RETURN new;
END;
$BODY$
language plpgsql;
问题:会有死锁?根据我的理解,可能会发生这样的情况:
_________
|__table__| <- executor #1 waits on executor #2 to be able to lock the whole table AND
|_________| executor #2 waits on executor #1 to be able to lock the whole table
|_________|
|_________| <- row is locked by executor #1
|_________|
|_________| <- row is locked by executor #2
看来只有选项是每次在交易开始时锁定整个表。
有你尝试将'transaction_summary'连接到您的锁定查询中,并应用'FOR UPDATE的transaction_summary'? (如果你在'transaction_summary'中有明确定义的主键,你可以保留整个表的锁定值) - 另外,也可以使用'FOUND'特殊变量来代替'rec_cnt'变量。 – pozs 2014-10-20 08:24:30
另外,你想用它达到什么目的?也许一个多线程安全UPSERT? http://stackoverflow.com/questions/17267417/how-do-i-do-an-upsert-merge-insert-on-duplicate-update-in-postgresql – pozs 2014-10-20 08:29:07
@Pozs - 是的,我想要得到的是一个线程安全_upsert_操作。一个插入_transaction table_可以在_transaction_summary_表上导致两个_upserts_。 PS:谢谢,我没有意识到有一个特殊的变量“FOUND” – robert 2014-10-20 08:47:29