Использую PGSQL.
Есть таблица записей ~ 1000 000 записей
SQL код:
CRE ATE TABLE forms (
id serial PRIMARY KEY,
account INT NOT NULL,
author text,
salary INT NOT NULL
);
INS ERT INTO forms(account, author, salary) VALUES
(1100889, 'Иванов', 30),
(1100889, 'Петров', 40),
(4443, 'Сидоров', 40),
(1100889, 'Сергеев', 50)
При авторизации пользователя в аккаунт идет пересчет поля salary в целом по аккаунту для всех пользователей
SQL код:
UPDATE forms
SET salary = (SEL ECT....)
WHERE account = 1100889
Перед обновление делаю блокировку по аккаунту с таймаутом 5 секунд.
SQL код:
BEGIN ISOLATION LEVEL READ COMMITTED READ WRITE;
SE T LOCAL statement_timeout = '5000ms';
SELECT PG_ADVISORY_XACT_LOCK("lock_id") FR OM (
SELECT UNNEST('{1100889}'::BIGINT[]) AS "lock_id"
) LocksId
RESET statement_timeout
В процессе обновления могут выполнятся обновления по конкретному сотруднику из этого аккаунта, я также ставлю
блокировку по аккаунту.
SQL код:
UPDATE forms
SE T salary = 100
WHERE account = 1100889 AND author = 'Иванов'
Когда общий запрос обновления по аккаунту (большой аккаунт) выполняется долго > 5 секунд,
то падает ошибка на второй запрос обновления
по сотруднику ошибка canceling statement due to statement timeout.
Понятно, что оптимальное решение ускорить запрос расчета целиком по аккаунту.
Плохо разбираюсь в тебе блокировок в PGSQL, просьба подсказать как исправить ситуацию с точки зрения
блокировок, в какую сторону смотреть?