Eu tenho uma tabela particionada user_stay
que possui muitos INSERTs e UPDATEs.
db=> \d user_stay;
Partitioned table "public.user_stay"
Column | Type | Collation | Nullable | Default
------------------+-----------------------------+-----------+----------+---------------------------------------
id | bigint | | not null | nextval('user_stay_id_seq'::regclass)
last_update_date | date | | not null | CURRENT_DATE
custom_place_id | bigint | | |
Foreign-key constraints:
"user_stay_custom_place_id_fkey" FOREIGN KEY (custom_place_id) REFERENCES user_custom_place(id) ON DELETE CASCADE
A partição é por last_update_date
. Quando tento anexar a nova tabela de partições para a data futura, ocorre o erro.
Por exemplo, hoje é 30/08 e tento criar a tabela para 02/09:
CREATE TABLE user_stay_partition_2023_09_02
(LIKE user_stay INCLUDING DEFAULTS INCLUDING CONSTRAINTS);
ALTER TABLE user_stay_partition_2023_09_02 ADD CONSTRAINT "2023_09_02"
CHECK ( last_update_date >= DATE '2023_09_02' AND
last_update_date < DATE '2023_09_03' );
ALTER TABLE user_stay ATTACH PARTITION user_stay_partition_2023_09_02
FOR VALUES FROM ('2023_09_02') to ('2023_09_03');
O erro é:
[7396]:ERROR: deadlock detected at character 13
[7396]:DETAIL: Process 7396 waits for RowExclusiveLock on relation 594728 of database 18604; blocked by process 31245.
Process 31245 waits for ShareRowExclusiveLock on relation 594672 of database 18604; blocked by process 7396.
Process 7396: INSERT INTO user_stay (last_update_date, ...) VALUES ('2023-08-30'::date, ...) ON CONFLICT DO NOTHING RETURNING user_stay.id
Process 31245: ALTER TABLE user_stay ATTACH PARTITION user_stay_partition_2023_09_02
FOR VALUES FROM ('2023_09_02') to ('2023_09_03');
Atualização 1
Acho que o motivo são os dois SQLs a seguir:
- INSERIR EM user_stay
- ALTER TABLE user_stay ANEXAR PARTIÇÃO
Ambos requerem o bloqueio de user_stay
& user_custom_place
. Se o SQL 1 obtiver o bloqueio user_stay
primeiro e o SQL 2 obtiver o bloqueio user_custom_place
primeiro, então será um impasse e ambos os SQLs não serão concluídos.
Atualização 2
Corrija o impasse bloqueando manualmente a tabela com a mesma ordem, para que o impasse desapareça:
BEGIN;
LOCK TABLE user_custom_place IN SHARE ROW EXCLUSIVE MODE;
ALTER TABLE user_stay ATTACH PARTITION user_stay_partition_2023_09_02
FOR VALUES FROM ('2023_09_02') to ('2023_09_03');
COMMIT;