Skip site navigation (1) Skip section navigation (2)

Re: [pgsql-ru-general] атомарно сохран

From: Nikolay Samokhvalov <samokhvalov(at)gmail(dot)com>
To: "Dmitry E(dot) Oboukhov" <unera(at)debian(dot)org>
Cc: pgsql-ru-general(at)postgresql(dot)org
Subject: Re: [pgsql-ru-general] атомарно сохран
Date: 2012-06-20 21:17:36
Message-ID: CANNMO+KOCWuH0zuawvZThz33S_7k9u+kMXyLqsY8tfEE8AG=_A@mail.gmail.com (view raw or flat)
Thread:
Lists: pgsql-ru-general
кстати, у нашего польского собрата по футбольному несчастью depesz-а совсем
свежий пост на эту тему, советую

http://www.depesz.com/2012/06/10/why-is-upsert-so-complicated/

2012/6/21 Nikolay Samokhvalov <samokhvalov(at)gmail(dot)com>

> 1) можно поменять местами -- пробуем вставлять, если ошибка, то делаем
> update
> 2) немного более правильно делать это "ближе к серверу", для этого можно
> написать plpgsql-функцию, см Example 39-2. Exceptions with UPDATE/INSERT
> http://www.postgresql.org/docs/9.1/static/plpgsql-control-structures.html#PLPGSQL-ERROR-TRAPPING
> 3) ещё правильнее (и моднее) -- это использовать CTE
> http://vibhorkumar.wordpress.com/2011/10/26/upsertmerge-using-writable-cte-in-postgresql-9-1/
>
>
> 2012/6/20 Dmitry E. Oboukhov <unera(at)debian(dot)org>
>
>>
>> приходят внешние данные с уникальным ID (uuid)
>>
>> нужно эту запись либо создать, либо проапдейтить новыми значениями
>>
>> делал так:
>>
>> dbh->begin_work;    # начали транзакцию
>>
>> my $record = dbh->single(   # попытка апдейта
>>    q{
>>        UPDATE
>>            table
>>        SET
>>            some=?
>>        WHERE
>>            eid=?
>>        RETURNING *
>>    }, $val, $eid
>> );
>>
>> unless ($record) {      # инсерт после неудачи апдейта
>>    my $record = dbh->single(
>>        q{
>>            INSERT INTO
>>                table
>>            (eid, some)
>>
>>            VALUES
>>                (?, ?)
>>            RETURNING *
>>        }, $eid, $val
>>    );
>>
>> }
>>
>> dbh->commit;        # коммит транзакции
>>
>>
>>
>> то есть в транзакции пытаемся сперва сделать апдейт имеющегося, а если
>> его нет в БД то затем делаем insert.
>>
>> так вот при таком подходе при приходе одновременных запросов иногда
>> падает на втором insert'е с жалобой что такой ключ уже существует.
>>
>> как правильно решить данную проблему?
>>
>> --
>>
>> . ''`.                               Dmitry E. Oboukhov
>> : :’  :   email: unera(at)debian(dot)org jabber://UNera(at)uvw(dot)ru
>> `. `~’              GPGKey: 1024D / F8E26537 2006-11-21
>>  `- 1B23 D4F8 8EC0 D902 0555  E438 AB8C 00CF F8E2 6537
>>
>> -----BEGIN PGP SIGNATURE-----
>> Version: GnuPG v1.4.10 (GNU/Linux)
>>
>> iEYEAREDAAYFAk/iF0cACgkQq4wAz/jiZTcyfACg0YDwJvZbxKBenjotM7WDdWL/
>> YJoAoNgQ6tz13jtNGlkIYdf4XGoATD/Y
>> =OQgr
>> -----END PGP SIGNATURE-----
>>
>>
>

In response to

pgsql-ru-general by date

Next:From: John NashDate: 2012-10-15 08:22:00
Subject: WebSphere Application Server support for postgres
Previous:From: Nikolay SamokhvalovDate: 2012-06-20 21:13:35
Subject: Re: [pgsql-ru-general] атомарно сохран

Privacy Policy | About PostgreSQL
Copyright © 1996-2014 The PostgreSQL Global Development Group