Re: Revisited: Transactions, insert unique. - Mailing list pgsql-general

From Ed Loehr
Subject Re: Revisited: Transactions, insert unique.
Date
Msg-id 3907AE94.C1639C08@austin.rr.com
Whole thread Raw
In response to RE: Revisited: Transactions, insert unique.  ("Hiroshi Inoue" <Inoue@tpf.co.jp>)
Responses RE: Revisited: Transactions, insert unique.
Re: Revisited: Transactions, insert unique.
Re: Revisited: Transactions, insert unique.
List pgsql-general
Hiroshi Inoue wrote:
>
> You should call SET TRANSACTION immediately after BEGIN.
> Note that SET TRANSACTION .. is per transaction command.
>
> PostgreSQL's SERIALIZABLE isolation level would allow both inserts.
> READ COMMITED isolation level wouldn't allow A's inserts.

Even if I call SET after BEGIN, it is not consistent with docs or the
standard (see pghackers discussion under same subject), as the two scripts
below seem to demonstrate.

[Rex:  There is a subtle difference between your sequence and mine.  Insert
from B first, and don't do any select from A before you attempt the insert,
as below.]

> As I mentioned in another posting,PostgreSQL's SERIALIZABLE
> isolation level isn't completely serializable and it's same as Oracle.
> Probably Vadim refers to this incomplete serializability somewhere
> in documentation.
> It seems almost impossible to implement complete serializability
> under MVCC without using table level locking. I love MVCC much
> more than theoretically beautiful complete serializability.

Interesting, thanks.  I certainly don't have any big gripes about PG
concurrency, as it has worked flawlessly for me so far with READ COMMITTED
level.  All this has been strictly in the interest of clarifying a
discrepancy between the docs/std and 7.0.  I could see it mattering to
some, but not for my app.

Regards,
Ed Loehr
===

This sequence, AFAICT, appears to fail the SERIALIZABLE standard, allowing
A to see effects from B that permute the serializability...

--------------------- START -----------------------------
-- Within transaction A --------------------------
DROP TABLE foo;
CREATE TABLE foo (id INTEGER, msg VARCHAR);
BEGIN;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

-- Within transaction B --------------------------
BEGIN;
--SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
INSERT INTO foo (id, msg)
        SELECT 1, 'From B'
        WHERE NOT EXISTS (SELECT * FROM foo WHERE id = 1);
COMMIT;
SELECT * FROM foo;

-- Within transaction A --------------------------
SELECT * FROM foo;
INSERT INTO foo (id, msg)
        SELECT 1, 'From A'
        WHERE NOT EXISTS (SELECT * FROM foo WHERE id = 1);
SELECT * FROM foo;
COMMIT;
--------------------- END -----------------------------


...while this sequence, which I would've thought to be functionally
identical, is compliant...


--------------------- START -----------------------------
-- Within transaction A ----------------------------
DROP TABLE foo;
CREATE TABLE foo (id INTEGER, msg VARCHAR);
BEGIN;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

-- Within transaction B ----------------------------
BEGIN;
INSERT INTO foo (id, msg)
        SELECT 1, 'From B'
        WHERE NOT EXISTS (SELECT * FROM foo WHERE id = 1);

-- Within transaction A ----------------------------
SELECT * FROM foo;  -- The magic query.

-- Within transaction B ----------------------------
COMMIT;
SELECT * FROM foo;

-- Within transaction A ----------------------------
SELECT * FROM foo;
INSERT INTO foo (id, msg)
        SELECT 1, 'From A'
        WHERE NOT EXISTS (SELECT * FROM foo WHERE id = 1);
SELECT * FROM foo;
COMMIT;

pgsql-general by date:

Previous
From: Tatsuo Ishii
Date:
Subject: Re: How to connect using pg_connect function from php3 ?
Next
From: Lincoln Yeoh
Date:
Subject: Re: Revisited: Transactions, insert unique.