Я использую экземпляр PostgreSQL RDS в AWS. По сути, существует запрос, который вставляет данные в первую таблицу, назовем ее table
. Там данные могут иметь дубликаты в некоторых полях (кроме, конечно, первичного ключа).
Затем есть триггер, который обновляет другую таблицу, infotable
, не допуская дубликатов.
Триггер:
CREATE TRIGGER insert_infotable AFTER INSERT ON table
FOR EACH ROW EXECUTE PROCEDURE insert_infotable();
Соответствующая часть функции триггера выглядит следующим образом:
CREATE OR REPLACE FUNCTION insert_infotable() RETURNS trigger AS $insert_infotable$
BEGIN
--some irrelevant code
IF NOT EXISTS (SELECT * FROM infotable WHERE col1 = NEW.col1 AND col2 = NEW.col2) THEN
INSERT INTO infotable(col1, col2, col3, col4, col5, col6) values (--some values--);
END IF;
RETURN NEW;
END;
$insert_infotable$ LANGUAGE plpgsql;
Таблица infotable
имеет уникальное ограничение для столбцов col1
и col2
.
В целом все работает нормально, но редко, примерно один раз в 1k вставок, триггер возвращает ошибку «значение дублированного ключа нарушает уникальное ограничение« unique_col1_and_col2 »» для таблицы infotable
. Этого не должно быть, поскольку в функции триггера есть часть IF NOT EXISTS
.
Первый вопрос: что может быть причиной этого? Единственное, что я могу вспомнить, это гонки, в которых два пользователя одновременно получают одну и ту же информацию, оба запускают триггер, но затем один обновляет вторую таблицу с помощью триггера, а второй пользователь получает ошибку дублирования. И из-за этого весь его запрос вставки завершается неудачно, включая вставку в основной файл table
.
Если это так, что я могу с этим поделать? Является ли использование блокировки при вставке хорошей идеей для таблицы, в которую должны вставлять данные более 100 пользователей одновременно?
И если да, то какой тип блокировки я должен использовать и какую таблицу я должен заблокировать - основную таблицу или вторую, которая модифицируется триггером? (или я думаю, должен ли я иметь блокировку с моим основным оператором вставки или внутри функции триггера?)