Postgres триггер и блокировка строк - PullRequest
0 голосов
/ 02 ноября 2018

Пожалуйста, помогите с моим пониманием того, как триггеры и блокировки могут взаимодействовать

Я массово загружаю записи в таблицу с такими инструкциями… ..

BEGIN;
INSERT INTO table_a VALUES (record1) , (record2), (record3)………;
INSERT INTO table_a VALUES (record91) , (record92), (record93)………;
…..
….
COMMIT;

В одной вставке может быть несколько сотен записей, а между COMMIT может быть несколько десятков операторов INSERT

Table_a имеет триггер, определенный как….

AFTER INSERT ON table_a FOR EACH ROW EXECUTE PROCEDURE foo();

Процедура foo () анализирует каждую новую строку по мере ее добавления и (среди прочего) обновляет запись в сводке table_b (уникально идентифицируется первичным ключом). Таким образом, для каждой записи, вставленной в table_a , соответствующая запись будет обновлена ​​в table_b

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

Вопросы - должно ли что-либо в операторах массовой вставки влиять на мой второй процесс, способный обновлять записи в table_b ? Я понимаю, что процесс массовой вставки будет получать блокировку строки каждый раз, когда обновляет строку в table_b , но когда будет снята эта блокировка строки? - когда была вставлена ​​отдельная запись (запись1, запись2, запись3 и т. Д.)? Или когда весь оператор INSERT завершен? Или когда достигнут COMMIT?

Дополнительная информация - моя общая задача для этого вопроса - попытаться понять, почему мой 2-й процесс иногда останавливается на минуту или более при попытке обновить строку в table_b, которая также обновляется Процесс массовой загрузки. То, что кажется происходящим, так это то, что блокировка целевой записи в table_b фактически не снимается, пока не будет достигнут COMMIT - что противоречит тому, что я думаю, должно быть происходит. (Я думаю, что блокировка строки должна быть снята, как только будет выполнено ОБНОВЛЕНИЕ этой строки)


ОБНОВЛЕНИЕ после ответа (ов) - да, конечно, вы оба правы. По-моему, я каким-то образом убедил себя, что отдельные обновления, выполняемые в триггере, каким-то образом отделены от общего BEGIN и COMMIT всей транзакции. Глупый я.

Практика добавления нескольких записей одним INSERT и нескольких INSERT между COMMIT была введена для повышения скорости массовой загрузки (что и происходит). Я забыл о побочном эффекте увеличения времени до снятия блокировок.

1 Ответ

0 голосов
/ 02 ноября 2018

Что должно произойти при откате транзакции? Совершенно очевидно, что все вставки в table_a,, а также все обновления в table_b, следует откатить. Вот почему все строки table_b, обновленные триггером, будут заблокированы до завершения транзакции.

Фиксация после каждого insert (уменьшение количества строк, вставленных в одну транзакцию) уменьшит вероятность конфликтов с параллельными процессами.

...