pg_log:
2016-01-20 23:00:31 UTC ERROR: deadlock detected
2016-01-20 23:00:31 UTC DETAIL:
Process 2696 waits for RowShareLock on relation 1849109 of database 1847373; blocked by process 2919.
Process 2919 waits for AccessExclusiveLock on relation 1848698 of database 1847373; blocked by process 2696.
Process 2696:
INSERT INTO install_session (
[..]
) VALUES (
[..]
)
Process 2919: DROP TABLE IF EXISTS install_view_2015_11_20
2016-01-20 23:00:31 UTC HINT: See server log for query details.
查询上述关系给了我:
select * from pg_class where oid = 1849109;
> install
select * from pg_class where oid = 1848698;
> app
问题:
INSERT
和DROP
的目标是两个不同的表格。Postgres 9.3
更新
我确实有triggers
:
CREATE OR REPLACE FUNCTION insert_install_session()
RETURNS TRIGGER AS $$
BEGIN
EXECUTE 'INSERT INTO install_session_'
|| to_char(NEW.created, 'YYYY_MM_DD') ||
' SELECT ($1).*'
USING NEW;
RETURN NULL;
END;
$$
LANGUAGE PLPGSQL
CREATE TRIGGER trigger_insert_install_session
BEFORE INSERT ON install_session
FOR EACH ROW EXECUTE PROCEDURE insert_install_session()
来自所有分区的和foreign keys
(在本例中为install_session_XXXX_XX_XX和install_view_XXXX_XX_XX)引用表app
和install
。
这使得事情变得更加清晰,但我仍然不明白为什么DROP
命令需要锁定除应该删除的表之外的任何表。
答案 0 :(得分:1)
我做了以下实验:
test=> CREATE TABLE aa( x int primary key );
CREATE TABLE
test=> CREATE TABLE bb( y int primary key, x int references aa(x) );
CREATE TABLE
test=> BEGIN;
BEGIN
test=> DROP TABLE bb;
DROP TABLE
test=>
在另一场会议中:
test=> select locktype, relation, relname,
test-> transactionid, mode, granted
test-> from pg_locks p
test-> left join pg_class c on p.relation = c.oid
test-> where locktype = 'relation'
test-> ;
locktype | relation | relname | transactionid | mode | granted
----------+----------+-----------------------------------+---------------+---------------------+---------
.........
.........
.........
.........
relation | 24739 | aa | | AccessExclusiveLock | t
relation | 24744 | bb | | AccessExclusiveLock | t
(13 wierszy)
似乎丢弃表B
需要对表'B'和'A'进行独占锁定。
为什么PostgeSQL需要将'A'与'B'区分开来?我真的不知道。
我认为我们能做的最好的事情就是将这一事实与生活相协调。
如果我们知道PostgreSQL需要对两个表进行独占锁定,那么死锁的原因现在已经很清楚了:
DROP TABLE B
的第二个事务必须获取表A
上的独占锁,并且必须等待事务#1
为了避免死锁,在执行第一次插入之前,在第一个事务中将表A放在AccessExclusiveLock上。