子表上的DROP TABLE被Postgres 9.5中的父表上的SELECT阻塞

时间:2017-06-22 04:12:09

标签: postgresql locking

我在表T和T_CHILD之间有父/子关系。当我从父-T中有一个Active事务SELECTING,并且我尝试删除子表(T_CHILD)时,DROP语句就会挂起,因为此会话试图在父表和子表上获得Access Exclusivelock。 /> 1.这是预期的行为吗? 2.为什么Postgres会阻止子表被删除,尽管删除子表对父表的SELECT没有影响?你能解释一下吗?

dev_sporuran=# \d+ t
                          Table "public.t"
 Column |  Type   | Modifiers | Storage | Stats target | Description
--------+---------+-----------+---------+--------------+-------------
 id     | integer | not null  | plain   |              |
Indexes:
    "t_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "t_child" CONSTRAINT "t_child_fk" FOREIGN KEY (t_id) REFERENCES t(id)

dev_sporuran=# \d+ t_child
                               Table "public.t_child"
 Column |         Type          | Modifiers | Storage  | Stats target | Description
--------+-----------------------+-----------+----------+--------------+-------------
 id     | integer               |           | plain    |              |
 t_id   | integer               |           | plain    |              |
 name   | character varying(10) |           | extended |              |
Foreign-key constraints:
    "t_child_fk" FOREIGN KEY (t_id) REFERENCES t(id)

***********26727 session starts a SELECT ********
dev_sporuran=# begin;
BEGIN
dev_sporuran=# select * from t;
 id
----
(0 rows)

*****26727 gets a shared lock for the SELECT on the table and the PK******
dev_sporuran=# select locktype,database,relation::regclass,transactionid,pid,mode,granted
from pg_locks where pid in (26727,26780) order by pid;
  locktype  | database | relation | transactionid |  pid  |      mode       | granted
------------+----------+----------+---------------+-------+-----------------+---------
 relation   | 19752133 | pg_locks |               | 26727 | AccessShareLock | t
 relation   | 19752133 | t_pkey   |               | 26727 | AccessShareLock | t
 relation   | 19752133 | t        |               | 26727 | AccessShareLock | t
 virtualxid |          |          |               | 26727 | ExclusiveLock   | t
(4 rows)


**************26827 tries to DROP the t_child table ************
dev_sporuran=# select pg_backend_pid();
 pg_backend_pid
----------------
          26867
(1 row)

dev_sporuran=# drop table t_child;


********* This just hangs;
Looking at pg_locks - 26867 requires not only an Access Exclusive lock on t_child, it also needs an Access Exclusive Lock on the parent table - T.  
 But it cannot get it, because 26727 has a Share lock on it thru the SELECT statement.  So it has to wait*****

dev_sporuran=# select locktype,virtualxid,relation::regclass,transactionid,pid,mode,granted
from pg_locks where pid in (26727,26867) and relation::regclass in ('t','t_pkey','t_child') order by pid;
 locktype | virtualxid | relation | transactionid |  pid  |        mode         | granted
----------+------------+----------+---------------+-------+---------------------+---------
 relation |            | t_pkey   |               | 26727 | AccessShareLock     | t
 relation |            | t        |               | 26727 | AccessShareLock     | t
 relation |            | t_child  |               | 26867 | AccessExclusiveLock | t
 relation |            | t        |               | 26867 | AccessExclusiveLock | f
(4 rows)

由于 穆拉利

1 个答案:

答案 0 :(得分:0)

看起来像你可以提出的关于pgsql-hackers的讨论。我一眼就看出它不应该是ExclusiveLock而不是AccessExclusiveLock,所以它仍然允许SELECT。但是大多数表结构的改变需要A.E.L。

看一下ALTER TABLE锁定强度降低补丁,看看这种情况有多复杂。