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
Views: Raw Message | Whole Thread | 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-----
>>
>>
>

In response to

Browse pgsql-ru-general by date

  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] атомарно сохранить или проапдейтить