| 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 | 
| Views: | Whole Thread | Raw Message | Download mbox | Resend email | 
| 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-----
>>
>>
>
| From | Date | Subject | |
|---|---|---|---|
| Next Message | John Nash | 2012-10-15 08:22:00 | WebSphere Application Server support for postgres | 
| Previous Message | Nikolay Samokhvalov | 2012-06-20 21:13:35 | Re: [pgsql-ru-general] атомарно сохранить или проапдейтить |