pg.ddx.io  pgsql-general@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Olivier Dony <odo+pggen@odoo.com>
To: pgsql-general@postgresql.org
Subject: Serialization errors despite KEY SHARE/NO KEY UPDATE
Date: Tue, 29 Sep 2015 16:47:21 +0200
Message-ID: <560AA479.4080807@odoo.com> (raw)
List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-general>

Using 9.3.9 and 9.4.4 I'm experiencing serialization errors that I
have trouble explaining based on the documentation.

The concurrent transactions are framework-driven and all of them
are running in REPEATABLE READ isolation level.

The error can be reproduced as shown below. T1 fails when acquiring
the second KEY SHARE lock for the same row, but does not fail if
only one of the T1 UPDATEs is executed, either the first or the second
one.

Is there some hidden read/write dependency at play here?

My understanding of the KEY SHARE/NO KEY UPDATE locks introduced in 9.3
was that they would avoid side-effects/blocking between transactions
that are only linked via FK constraints, as long as the target PK was
not touched. Isn't it the case here?

If not, is there a reliable way to make T2 fail instead of T1 in such
situations? I've tried adding an explicit
     "SELECT date FROM users WHERE id = 1 FOR UPDATE NOWAIT"
at the beginning of T2 but that doesn't block at all.

Thanks for the clarifications!


-- Setup tables
CREATE TABLE users ( id serial PRIMARY KEY,
                       name varchar,
                       date timestamp );
CREATE TABLE orders ( id serial PRIMARY KEY,
                        name varchar,
                        user_id int REFERENCES users (id) );
INSERT INTO users (id, name) VALUES (1, 'foo');
INSERT INTO orders (id, name) VALUES (1, 'order 1');


-- Run 2 concurrent transactions: T1 and T2
              T1                                T2
|-----------------------------|----------------------------------|
    BEGIN ISOLATION LEVEL
          REPEATABLE READ;

    UPDATE orders
    SET name = 'order of foo',
        user_id = 1
    WHERE id = 1;

                                      BEGIN ISOLATION LEVEL
                                            REPEATABLE READ;

                                      UPDATE users
                                      SET date = now()
                                      WHERE id = 1;

                                      COMMIT;

    UPDATE orders
    SET name = 'order of foo (2)',
        user_id = 1
    WHERE id = 1;

T1 fails with:
ERROR:  could not serialize access due to concurrent update
CONTEXT:  SQL statement "SELECT 1 FROM ONLY "public"."users" x WHERE "id" 
OPERATOR(pg_catalog.=) $1 FOR KEY SHARE OF x"



--
Olivier


-- 
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general



view thread (8+ messages)  latest in thread

Message-ID: <560AA479.4080807@odoo.com>
Permalink:  ../560AA479.4080807@odoo.com/
Also on:    postgresql.org/message-id/560AA479.4080807@odoo.com

 · 

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-general@postgresql.org
  Cc: odo+pggen@odoo.com
  Subject: Re: Serialization errors despite KEY SHARE/NO KEY UPDATE
  In-Reply-To: <560AA479.4080807@odoo.com>

* 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