PostgreSQL одновременное увеличение счетчика


9

Мне нужно вести статистическую таблицу для проекта, составленную из списка элементов и их использования (Подумайте о чем-то вроде веб-сайта, на котором вы хотели бы подсчитывать просмотры страниц). Каждый раз, когда создается элемент, мне нужно увеличивать использование определенного элемента.

Моя первая реализация:

statistics(
  id      integer NOT NULL,
  name    character varying(255) NOT NULL,
  usage   integer NOT NULL DEFAULT 0,
);


UPDATE statistics 
  SET usage = usage + 1
WHERE name = '<name>';

Мои опасения касаются производительности и параллелизма. Процесс обновления будет реализован несколькими десятками (может быть, 80-120) устройств и может происходить несколько раз в секунду, поэтому мои вопросы:

1) сохранит ли этот метод параллелизм? (т.е. если более одного устройства запрашивают обновление «одновременно», будет ли учитываться каждый запрос?)

2) Можете ли вы предложить лучший способ достижения результата? Я ожидаю, что у меня будет нагрузка при написании обновлений, в то время как чтение будет гораздо более частым. Существует ли специальная функция для увеличения значений? Я смотрю на «последовательность», но я не уверен, что это правильный путь ...

Заранее большое спасибо за любые советы

Ответы:


5

Второе обновление будет ожидать завершения предыдущего обновления в тех же строках, но затем увидит зафиксированное значение.

Предположим, две параллельные транзакции обновляют одну и ту же строку с начальным значением 0

Время перехода 1 значение T1 Транзакция 2 значение T2
-------------------------------------------------- ------------
1 обновление ... 1 0
2 1 обновление .. "undefined"
                                (ожидание) 
3 совершить 1 2
4 1 коммит 2
5 2 2 

«Значение T1» и «Значение T2» означает значение, которое видит эта транзакция.

Если вы хотите убедиться, что вы ловите ситуации, в которых есть «несовместимые» изменения (например, одна транзакция, устанавливающая в usageстолбце определенное значение, а не просто увеличивает его), вы можете перевести все транзакции на «сериализуемый» уровень изоляции. Но тогда вам нужно будет подготовиться к обработке ошибок.

Обновления для разных имен могут выполняться одновременно без ожидания (поскольку затрагиваются разные строки).

SELECTs никогда не будет заблокирован, но будет видеть только соответствующие значения.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.