Какую явную блокировку использовать для триггера? - PullRequest
1 голос
/ 12 апреля 2019

Я пытаюсь понять, какой тип блокировки использовать для функции триггера.

Упрощенная функция:

CREATE OR REPLACE FUNCTION max_count() RETURNS TRIGGER AS
$$
  DECLARE
    max_row           INTEGER := 6;
    association_count INTEGER := 0;
  BEGIN
    LOCK TABLE my_table IN ROW EXCLUSIVE MODE;

    SELECT INTO association_count COUNT(*) FROM my_table WHERE user_id = NEW.user_id;

    IF association_count > max_row THEN
      RAISE EXCEPTION 'Too many rows';
    END IF;
    RETURN NEW;
  END;
$$ LANGUAGE plpgsql;

CREATE CONSTRAINT TRIGGER my_max_count
AFTER INSERT OR UPDATE ON my_table
DEFERRABLE INITIALLY DEFERRED
FOR EACH ROW
EXECUTE PROCEDURE max_count();

Я изначально планировал использовать EXCLUSIVE, но он кажется слишком тяжелым. Что я действительно хочу, так это убедиться, что во время выполнения этой функции в таблицу не добавляются новые строки с соответствующими user_id.

1 Ответ

1 голос
/ 12 апреля 2019

Если вы хотите предотвратить изменение таблицы при одновременных транзакциях, блокировка SHARE будет правильной. Но это может привести к тупику, если две такие транзакции будут выполняться одновременно & mdash; каждая изменила несколько строк и блокируется другой, когда пытается увеличить блокировку таблицы.

Более того, все блокировки таблиц, конфликтующие с SHARE UPDATE EXCLUSIVE, приведут к отмене автоочистки, что приведет к переполнению таблицы, когда это происходит слишком часто.

Так что держитесь подальше от настольных замков, они обычно неправильные.

Лучший способ сделать это - вообще не использовать явную блокировку, а использовать уровень изоляции SERIALIZABLE для всех транзакций, которые обращаются к этой таблице.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...