ProHoster > Bloc > Administració > Antipatterns de PostgreSQL: canvieu les dades sense passar un activador
Antipatterns de PostgreSQL: canvieu les dades sense passar un activador
Tard o d'hora, molts s'enfronten a la necessitat de solucionar massivament alguna cosa als registres de la taula. Ja tinc digues-me com fer-ho millor, i com - és millor no fer-ho. Avui parlaré del segon aspecte de l'actualització massiva: sobre els desencadenants.
Per exemple, en una taula en què cal arreglar alguna cosa, penja un disparador dolent ON UPDATE, transferint tots els canvis a alguns agregats. I cal actualitzar-ho tot (inicialitzar un camp nou, per exemple) amb tanta cura que aquests agregats no es vegin afectats.
Només desactivem els activadors!
BEGIN;
ALTER TABLE ... DISABLE TRIGGER ...;
UPDATE ...; -- тут долго-долго
ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;
De fet, això és tot... tot està penjat.
Perquè ALTER TABLE imposa Accés exclusiu- un pany sota el qual ningú corre en paral·lel, ni tan sols un simple SELECT, no podrà llegir res de la taula. És a dir, fins que acabi aquesta transacció, tots els que vulguin "només llegir" esperaran. I això ho recordem UPDATE tenim un llarg...
Apaguem-lo ràpidament i després encenem-lo ràpidament!
BEGIN;
ALTER TABLE ... DISABLE TRIGGER ...;
COMMIT;
UPDATE ...;
BEGIN;
ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;
Aquí la situació ja és millor, el temps d'espera és molt menor. Però només dos problemes fan malbé tota la bellesa:
ALTER TABLE ell mateix espera totes les altres operacions sobre la taula, incloses les llargues SELECT
Mentre el disparador està apagat "volar per" qualsevol canvi a la taula, ni tan sols la nostra. I no entrarà als agregats, encara que hauria de ser. Problemes!
Gestió de variables de sessió
Per tant, a la versió anterior, ens vam trobar amb un punt fonamental: hem d'ensenyar d'alguna manera el desencadenant a distingir els "nostres" canvis a la taula dels "no els nostres". Els "nostres" es salten tal com estan, però en "no els nostres" es desencadenen. Per a això podeu utilitzar variables de sessió.
El mecanisme d'activació també es veu afectat per la variable de configuració rol_de_replicació de sessió. Activats sense instruccions addicionals (per defecte), els activadors s'activaran quan la funció de replicació sigui "origen" (predeterminada) o "local". Activadors activats especificant ENABLE REPLICA, només funcionarà si mode de sessió actual - "rèplica" i activadors activats especificant ENABLE ALWAYS, funcionarà independentment del mode de replicació actual.
Destacaré especialment que la configuració no s'aplica a tots alhora, ja que ALTER TABLE, però només a la nostra connexió especial separada. En total, perquè cap aplicació desencadenant funcioni:
SET session_replication_role = replica; -- выключили триггеры
UPDATE ...;
SET session_replication_role = DEFAULT; -- вернули в исходное состояние
Condició dins del disparador
Però l'opció anterior funciona per a tots els activadors alhora (o cal "alternar" per endavant els activadors que no voleu desactivar). I si necessitem "apaga" un activador específic?
Els noms dels paràmetres d'extensió s'escriuen de la següent manera: el nom de l'extensió seguit d'un punt i després el propi nom del paràmetre, de manera similar als noms d'objecte complets a SQL. Per exemple: plpgsql.variable_conflict.
Com que les opcions fora del sistema es poden establir en processos que no carreguen el mòdul d'extensió adequat, PostgreSQL accepta valors per a qualsevol nom amb dos components.
Primer, finalitzem el disparador, una cosa així:
BEGIN
-- процессу конвертации можно делать все
IF current_setting('mycfg.my_table_convert_process') = 'TRUE' THEN
IF TG_OP IN ('INSERT', 'UPDATE') THEN
RETURN NEW;
ELSE
RETURN OLD;
END IF;
END IF;
...
Per cert, això es pot fer "amb benefici", sense bloquejar, a través CREATE OR REPLACE per a la funció de disparador. I després, a la connexió especial, anotem la "nostra" variable:
SET mycfg.my_table_convert_process = 'TRUE';
UPDATE ...;
SET mycfg.my_table_convert_process = ''; -- вернули в исходное состояние
Coneixes altres maneres? Comparteix en els comentaris.