pg.ddx.io  pgsql-committers@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
To: pgsql-committers@lists.postgresql.org
Subject: pgsql: Avoid spurious deadlocks when upgrading a tuple lock
Date: Tue, 18 Jun 2019 22:24:38 +0000
Message-ID: <E1hdMWs-0004ib-QQ@gemulon.postgresql.org> (raw)

Avoid spurious deadlocks when upgrading a tuple lock

This puts back reverted commit de87a084c0a5, with some bug fixes.

When two (or more) transactions are waiting for transaction T1 to release a
tuple-level lock, and transaction T1 upgrades its lock to a higher level, a
spurious deadlock can be reported among the waiting transactions when T1
finishes.  The simplest example case seems to be:

T1: select id from job where name = 'a' for key share;
Y: select id from job where name = 'a' for update; -- starts waiting for T1
Z: select id from job where name = 'a' for key share;
T1: update job set name = 'b' where id = 1;
Z: update job set name = 'c' where id = 1; -- starts waiting for T1
T1: rollback;

At this point, transaction Y is rolled back on account of a deadlock: Y
holds the heavyweight tuple lock and is waiting for the Xmax to be released,
while Z holds part of the multixact and tries to acquire the heavyweight
lock (per protocol) and goes to sleep; once T1 releases its part of the
multixact, Z is awakened only to be put back to sleep on the heavyweight
lock that Y is holding while sleeping.  Kaboom.

This can be avoided by having Z skip the heavyweight lock acquisition.  As
far as I can see, the biggest downside is that if there are multiple Z
transactions, the order in which they resume after T1 finishes is not
guaranteed.

Backpatch to 9.6.  The patch applies cleanly on 9.5, but the new tests don't
work there (because isolationtester is not smart enough), so I'm not going
to risk it.

Author: Oleksii Kliukin
Discussion: https://postgr.es/m/B9C9D7CD-EB94-4635-91B6-E558ACEC0EC3@hintbits.com
Discussion: https://postgr.es/m/2815.1560521451@sss.pgh.pa.us

Branch
------
REL_11_STABLE

Details
-------
https://git.postgresql.org/pg/commitdiff/5246d3e791033267516b66ce3518f9cc6c23c261

Modified Files
--------------
src/backend/access/heap/README.tuplock             |  10 ++
src/backend/access/heap/heapam.c                   |  83 ++++++---
.../expected/tuplelock-upgrade-no-deadlock.out     | 195 +++++++++++++++++++++
src/test/isolation/isolation_schedule              |   1 +
.../specs/tuplelock-upgrade-no-deadlock.spec       |  72 ++++++++
5 files changed, 340 insertions(+), 21 deletions(-)



view thread (32+ messages)  latest in thread

Message-ID: <E1hdMWs-0004ib-QQ@gemulon.postgresql.org>
Permalink:  ../E1hdMWs-0004ib-QQ@gemulon.postgresql.org/
Also on:    postgresql.org/message-id/E1hdMWs-0004ib-QQ@gemulon.postgresql.org

 · 

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-committers@postgresql.org
  Cc: alvherre@alvh.no-ip.org, pgsql-committers@lists.postgresql.org
  Subject: Re: pgsql: Avoid spurious deadlocks when upgrading a tuple lock
  In-Reply-To: <E1hdMWs-0004ib-QQ@gemulon.postgresql.org>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox