Re: Why postgres take RowExclusiveLock on all partition

From: Sachin Kotwal <kotsachin(at)gmail(dot)com>
To: Ashutosh Bapat <ashutosh(dot)bapat(at)enterprisedb(dot)com>
Cc: PostgreSQL Developers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: Why postgres take RowExclusiveLock on all partition
Date: 2016-09-16 13:42:05
Message-ID: CA+N_YAc5soDwYgb0jaB_59iud1xUEi_g-B7AHHeksm_g-FV78Q@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi Ashutosh,

Thanks for reply.

Below are my findings:

In 1 Terminal:

postgres=# create table t1 (a int, b int);
CREATE TABLE
postgres=# show constraint_exclusion ;
constraint_exclusion
----------------------
partition
(1 row)
postgres=# create table t1_p1() inherits (t1);
CREATE TABLE
postgres=# alter table t1_p1 add constraint a_part check (a > 0 and a <
100);
ALTER TABLE
postgres=# create table t1_p2() inherits (t1);
CREATE TABLE
postgres=# alter table t1_p2 add constraint a_part check (a > 100 and a <
200);
ALTER TABLE
postgres=# insert into t1_p1 select i,i from generate_series(1, 5) i;
INSERT 0 5
postgres=# insert into t1_p2 select i,i from generate_series(101, 105) i;
INSERT 0 5
postgres=# select * from t1_p1;
a | b
---+---
1 | 1
2 | 2
3 | 3
4 | 4
5 | 5
(5 rows)
postgres=# select * from t1_p2;
a | b
-----+-----
101 | 101
102 | 102
103 | 103
104 | 104
105 | 105
(5 rows)
postgres=# begin;
BEGIN
postgres=# update t1 set b=555 where a=101;
UPDATE 1

In another Terminal :

postgres=# select locktype, database::regclass ,
relation::regclass,virtualtransaction, pid, mode , granted from pg_locks
where locktype='relation';
locktype | database | relation | virtualtransaction | pid | mode
| granted
----------+----------+----------+--------------------+-------+------------------+---------
relation | 13241 | pg_locks | 3/3867 | 28635 |
AccessShareLock | t
relation | 13241 | t1_p2 | 2/14038 | 28633 |
RowExclusiveLock | t
relation | 13241 | t1_p1 | 2/14038 | 28633 |
RowExclusiveLock | t
relation | 13241 | t1 | 2/14038 | 28633 |
RowExclusiveLock | t
(4 rows)

Hope above findings will help you to understand problem.

Regards,
Sachin

On Fri, Sep 16, 2016 at 6:20 PM, Ashutosh Bapat <
ashutosh(dot)bapat(at)enterprisedb(dot)com> wrote:

> On Fri, Sep 16, 2016 at 4:31 PM, Sachin Kotwal <kotsachin(at)gmail(dot)com>
> wrote:
> > Hi Hackers,
> >
> >
> > I checked if there is update transaction on master table involved in
> > partition.
> > Postgresql takes RowExclusiveLock on all partition tables.
> >
> > constraint exclusion is set to on.
>
> I checked this under the debugger and found that only the partitions
> which are scanned. The partitions excluded by constraints are not
> locked.
>
> postgres=# create table t1 (a int);
> CREATE TABLE
> postgres=# set constraint_exclusion to partition;
> SET
> postgres=# create table t1_p1() inherits (t1);
> CREATE TABLE
> postgres=# alter table t1_p1 add constraint a_part check (a > 0 and a <
> 100);
> ALTER TABLE
> postgres=# create table t1_p2() inherits (t1);
> CREATE TABLE
> postgres=# alter table t1_p2 add constraint a_part check (a > 100 and a <
> 200);
> ALTER TABLE
> postgres=# insert into t1_p1 select i from generate_series(1, 5) i;
> INSERT 0 5
> postgres=# insert into t1_p2 select i from generate_series(101, 105) i;
> INSERT 0 5
> postgres=# explain verbose select * from t1 where a > 100;
> QUERY PLAN
> ---------------------------------------------------------------------
> Append (cost=0.00..41.88 rows=851 width=4)
> -> Seq Scan on public.t1 (cost=0.00..0.00 rows=1 width=4)
> Output: t1.a
> Filter: (t1.a > 100)
> -> Seq Scan on public.t1_p2 (cost=0.00..41.88 rows=850 width=4)
> Output: t1_p2.a
> Filter: (t1_p2.a > 100)
> (7 rows)
>
> postgres=# explain verbose update t1 set a = a where a > 100;
> QUERY PLAN
> ----------------------------------------------------------------------
> Update on public.t1 (cost=0.00..41.88 rows=851 width=10)
> Update on public.t1
> Update on public.t1_p2
> -> Seq Scan on public.t1 (cost=0.00..0.00 rows=1 width=10)
> Output: t1.a, t1.ctid
> Filter: (t1.a > 100)
> -> Seq Scan on public.t1_p2 (cost=0.00..41.88 rows=850 width=10)
> Output: t1_p2.a, t1_p2.ctid
> Filter: (t1_p2.a > 100)
> (9 rows)
>
> The RowExclusiveLock is taken in InitPlan(), which is called after the
> partitions have been excluded.
>
> 817│ foreach(l, resultRelations)
> 818│ {
> 819│ Index resultRelationIndex =
> lfirst_int(l);
> 820│ Oid resultRelationOid;
> 821│ Relation resultRelation;
> 822│
> 823│ resultRelationOid =
> getrelid(resultRelationIndex, rangeTable);
> 824├> resultRelation =
> heap_open(resultRelationOid, RowExclusiveLock);
> 825│ InitResultRelInfo(resultRelInfo,
> 826│
> resultRelation,
> 827│
> resultRelationIndex,
> 828│
> estate->es_instrument);
> 829│ resultRelInfo++;
> 830│ }
>
> It does lock the parent table, since inheritance allows to have rows
> in that table. If the constraints on that table are not enough to
> exclude it by conditions, it will be scanned.
>
> Am I missing something? It might help to have SQL commands you are
> running. Also, can you please explain why do you think all the
> partitions are locked in RowExclusiveLock mode.
>

--

Thanks and Regards,
Sachin Kotwal

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Jeevan Chalke 2016-09-16 13:45:33 Re: Aggregate Push Down - Performing aggregation on foreign server
Previous Message Tom Lane 2016-09-16 13:37:08 Re: Printing bitmap objects in the debugger