Re: Solution to UPDATE...INSERT problem

From: Lincoln Yeoh <lyeoh(at)pop(dot)jaring(dot)my>
To: "Christopher Kings-Lynne" <chriskl(at)familyhealth(dot)com(dot)au>, "Hackers" <pgsql-hackers(at)postgresql(dot)org>, <pgsql-general(at)postgresql(dot)org>
Subject: Re: Solution to UPDATE...INSERT problem
Date: 2003-03-27 09:19:18
Message-ID: 5.1.0.14.1.20030327170544.029b07a0@mbox.jaring.my
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general pgsql-hackers

AFAIK the "except" select won't see other inserts in uncommitted
transactions. If those transactions are committed you will end up with the
same problem. You can try it yourself, by manually doing two separate
transactions in psql.

You either have to lock the whole table, or lock at the application layer.
Some time back I suggested a "lock on arbitrary string" feature for
postgresql for this and various other purposes, but that feature probably
wouldn't scale in terms of management (it requires 100% cooperation amongst
all apps/clients involved).

There's no "select * from table where pkey=x for insert;" which would block
on uncommitted inserts/updates of pkey=x and other selects for insert/update.

In contrast "select ... for update" blocks on committed stuff.

Regards,
Link.

At 09:55 AM 3/27/03 +0800, Christopher Kings-Lynne wrote:

>Hi Guys,
>
>I just thought I'd share with you guys a very clever solution to the old
>'update row. if no rows affected, then insert the row' race condition
>problem. A guy at my work came up with it.
>
>We were discussing this earlier on -hackers, but no-one could find a
>solution that didn't involve locking the entire table around the
>update...insert commands.
>
>The problem is that sometimes the row will be inserted by another process
>between your update and insert, causing your insert to fail with a unique
>constraint violation.
>
>So, say this is the insert:
>
>INSERT INTO table VALUES (1, 'foo'); // 1 is in the primary key column
>
>Rewrite it like this:
>
>INSERT INTO table SELECT 1, 'foo' EXCEPT SELECT 1, 'foo' FROM table WHERE
>pkcol=1;
>
>See? So now that INSERT statement will insert the row if it doesn't exist,
>or insert zero rows if it does. You are then guaranteed that your
>transaction will not fail and rollback, so you can repeat your update, or do
>the insert first and then the update, etc.
>
>Hope that's handy for people,
>
>Chris
>
>
>---------------------------(end of broadcast)---------------------------
>TIP 1: subscribe and unsubscribe commands go to majordomo(at)postgresql(dot)org

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Csaba Nagy 2003-03-27 09:19:48 Re: transaction blocking inserts in postgresql 7.3
Previous Message Tom Lane 2003-03-27 07:13:28 Re: Solution to UPDATE...INSERT problem

Browse pgsql-hackers by date

  From Date Subject
Next Message Christopher Kings-Lynne 2003-03-27 09:28:42 Re: [GENERAL] Solution to UPDATE...INSERT problem
Previous Message Hiroshi Inoue 2003-03-27 09:06:39 Re: updateable cursors & visibility