Förr eller senare stöter mĂ„nga pĂ„ nödvĂ€ndigheten av att massĂ€ndra poster i en tabell. Jag har redan , och hur man â hellre inte gör det. Idag kommer jag att prata om den andra aspekten av massuppdatering â om triggers.
Till exempel, i en tabell dÀr du behöver Àndra nÄgot, hÀnger det en elak trigger ON UPDATE, som flyttar alla Àndringar till olika aggregat. Och du vill uppdatera allt (initiera ett nytt fÀlt, till exempel) sÄ försiktigt att dessa aggregat inte pÄverkas.
LÄt oss bara stÀnga av triggerna!
BEGIN;
ALTER TABLE ... DISABLE TRIGGER ...;
UPDATE ...; -- hÀr tar det lÄng tid
ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;Egentligen Ă€r det allt â allt hĂ€nger redan.
För att ALTER TABLE det lĂ€gger pĂ„ AccessExclusive-lĂ„sning, vilket innebĂ€r att ingen process som körs parallellt, inte ens en enkel VĂLJ, kan lĂ€sa nĂ„got frĂ„n tabellen. Det vill sĂ€ga, sĂ„ lĂ€nge denna transaktion inte Ă€r avslutad, kommer alla som vill "bara lĂ€sa" att vĂ€nta. Och vi minns att UPPDATERA vi har en la-a-ang tidâŠ
LÄt oss dÄ snabbt stÀnga av den, sen snabbt slÄ pÄ den igen!
BEGIN;
ALTER TABLE ... DISABLE TRIGGER ...;
COMMIT;
UPDATE ...;
BEGIN;
ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;HÀr Àr situationen redan bÀttre, vÀntetiden Àr avsevÀrt mindre. Men tvÄ problem förstör hela skönheten:
ALTER TABLEsjĂ€lva vĂ€ntar pĂ„ alla andra operationer pĂ„ tabellen, inklusive de lĂ„ngaVĂLJ- SĂ„ lĂ€nge triggern Ă€r avstĂ€ngd, "flyger förbi" varje förĂ€ndring i tabellen, Ă€ven om det inte Ă€r vĂ„rt. Och i aggregaten kommer det pĂ„ inget sĂ€tt att hamna, Ă€ven om det borde. MĂ„let!
Hantera sessionvariabler
SĂ„, i den föregĂ„ende varianten stöter vi pĂ„ en principiell punkt â vi mĂ„ste pĂ„ nĂ„got sĂ€tt lĂ€ra triggern att sĂ€rskilja "vĂ„ra" Ă€ndringar i tabellen frĂ„n "inte vĂ„ra". "VĂ„ra" ska passera som de Ă€r, och för "inte vĂ„ra" â trigga. För detta kan vi anvĂ€nda .
session_replication_role
Vi lÀser :
Mekanismen för triggeraktivering pÄverkas ocksÄ av konfigurationsvariabeln . Aktiverade utan ytterligare instruktioner (standard) kommer triggers att aktiveras nÀr replikeringsrollen Àr - "origin" (standard) eller "local". Triggers som aktiveras genom att ange
ENABLE REPLICA, aktiveras bara om den aktuella sessionslÀget Àr - "replica", medan triggers som aktiveras genom att angeENABLE ALWAYS, kommer att aktiveras oavsett det aktuella replikeringslÀget.
Jag betonar sÀrskilt att instÀllningen gÀller inte för alla direkt, som ALTER TABLE, men bara till vÄr separata specialkoppling. SÄledes, för att inga applikationstriggare ska aktiveras:
SET session_replication_role = replica; -- stÀngde av triggare
UPDATE ...;
SET session_replication_role = DEFAULT; -- ÄterstÀllning till ursprungligt tillstÄndVillkoret inom triggar
Men det ovanstÄende alternativet fungerar för alla triggare samtidigt (eller mÄste vi "alterera" i förvÀg de triggare vi inte vill stÀnga av). Och om vi behöver stÀnga av" en specifik trigger?
Det hÀr hjÀlper oss med :
Namn pÄ parameterar i tillÀgg skrivs pÄ följande sÀtt: tillÀggens namn, punkt och sedan sjÀlva parameterens namn, liknande fullstÀndiga objektnamn i SQL. Till exempel: plpgsql.variable_conflict.
Eftersom externa parametrar kan stÀllas in i processer som inte laddar motsvarande tillÀggsmodul, accepterar PostgreSQL vÀrden för alla namn med tvÄ komponenter.
Först justerar vi triggar, ungefÀr sÄ hÀr:
BEGIN
-- omvandlingsprocessen kan göra allt
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;
... Förresten, detta kan göras "live", utan lÄsning, genom CREATE OR REPLACE för triggerfunktionen. Och sedan stÀller vi in "vÄr" variabel i specialkopplingen:
SET mycfg.my_table_convert_process = 'TRUE';
UPDATE ...;
SET mycfg.my_table_convert_process = ''; -- ÄterstÀllning till ursprungligt tillstÄnd
KÀnner du till andra sÀtt? Dela med dig i kommentarerna.
KĂ€lla: habr.com
