Как безопасно ВСТАВИТЬ / ОБНОВИТЬ значение в Postgres в многопоточной среде - PullRequest
1 голос
/ 22 ноября 2011

У меня есть таблица в PostgreSQL, которая выглядит следующим образом:

 create table item_counts {
  item string,
  view_count int}

Я хотел бы использовать эту таблицу для отслеживания случаев появления item , увеличивая при необходимости значения.Первоначально таблица не заполнена, поэтому новое значение вставляется, если оно наблюдается впервые, в противном случае view_count увеличивается.Скорость и многозадачность - оба проблемы.

Я знаю, что могу сделать

rows_affected = execute("update item_counts set view_count = view_count + 1 
  where item = ?")
if rows_affected == 0:
   execute("insert into item_counts ...")

Однако в многопоточной среде это небезопасно, поэтому мне пришлось бы заключить его в транзакцию.Это, в свою очередь, уменьшит скорость, поскольку после каждой вставки / обновления будет происходить фиксация.

Есть предложения, как это сделать чистым и эффективным способом?

Ответы [ 2 ]

2 голосов
/ 22 ноября 2011

Если вы используете 9.1, вы можете рассмотреть возможность записи CTE:

http://vibhorkumar.wordpress.com/2011/10/26/upsertmerge-using-writable-cte-in-postgresql-9-1/

http://xzilla.net/blog/2011/Mar/Upserting-via-Writeable-CTE.html

0 голосов
/ 22 ноября 2011

Кроме того, вы можете установить контрольную точку, insert и update при нарушении уникального исключения (откат контрольной точки).Сомнительно, лучше ли это, особенно если вы ожидаете в основном обновлением.

Также транзакция в случае параллелизма все еще может завершиться неудачей при фиксации.

Также вы можете выполнить insertselect, вставляя то, что НЕ в таблице (используя предложение self-left-join или где не существует, как вам угодно), и затем обновляйте, если оно возвращает 0 затронутых строк.

И, возможно, лучше, еслиВы делаете это в функции на стороне сервера.

...