我在红移中编写了一个ETL进程,我真的希望它可以更加并行化。该过程创建了一堆临时表,然后将它们合并到主表中,在这样的事务中:
CREATE TEMPORARY TABLE temporary_table
(LIKE production_table);
BEGIN TRANSACTION;
LOCK TABLE production_table;
/* Dedupe and then insert */
DELETE FROM temporary_table
USING production_table
WHERE temporary_table.id = production_table.id
AND temporary_table.date <= production_table.date;
INSERT INTO production_table
SELECT * FROM temporary_table;
END TRANSACTION;
我希望LOCK TABLE production_table;
查询可以阻止,直到任何其他事务完成,但每当我尝试在实践中运行它时,我得到:
ERROR: deadlock detected
DETAIL: Process 4868 waits for AccessExclusiveLock on relation 165643 of database 154587; blocked by process 4863.
Process 4863 waits for AccessExclusiveLock on relation 165643 of database 154587; blocked by process 4868.
这发生在两个delete / insert语句之间。为什么锁表步骤不能防止死锁?如何构建我的写入以便它们阻塞直到另一个事务完成?
答案 0 :(得分:2)
我已经弄明白了。
只要你做
,production_table
就会隐含锁定
CREATE TEMPORARY TABLE temporary_table
(LIKE production_table)
表示临时表的生命周期。我在创建临时表查询中使用了生产表的实际模式,并且死锁消失了。