ProHoster > blog > Utawala > Antipatterns za PostgreSQL: badilisha data kwa kupitisha kichochezi
Antipatterns za PostgreSQL: badilisha data kwa kupitisha kichochezi
Hivi karibuni au baadaye, wengi wanakabiliwa na hitaji la kurekebisha kitu kwenye rekodi za jedwali. Mimi tayari niambie jinsi ya kuifanya vizuri zaidi, na jinsi gani - ni bora si kufanya hivyo. Leo nitazungumza juu ya kipengele cha pili cha sasisho la wingi - kuhusu vichochezi.
Kwa mfano, kwenye meza ambayo unahitaji kurekebisha kitu, trigger mbaya hutegemea ON UPDATE, kuhamisha mabadiliko yote kwa baadhi ya jumla. Na unahitaji kusasisha kila kitu (anzisha uga mpya, kwa mfano) kwa uangalifu sana ili hesabu hizi zisiathiriwe.
Wacha tuzima vichochezi!
BEGIN;
ALTER TABLE ... DISABLE TRIGGER ...;
UPDATE ...; -- ΡΡΡ Π΄ΠΎΠ»Π³ΠΎ-Π΄ΠΎΠ»Π³ΠΎ
ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;
Kwa kweli, hiyo ndiyo yote - kila kitu kinaning'inia.
Kwa sababu ALTER TABLE inalazimisha Ufikiaji wa Kipekee- kufuli ambayo hakuna mtu anayeendesha sambamba, hata rahisi SELECT, haitaweza kusoma chochote kutoka kwenye meza. Hiyo ni, mpaka shughuli hii itaisha, kila mtu ambaye anataka hata "kusoma" tu atasubiri. Na tunakumbuka hilo UPDATE tuna muda mrefu...
Hebu tuizime haraka, kisha tuiwashe haraka!
BEGIN;
ALTER TABLE ... DISABLE TRIGGER ...;
COMMIT;
UPDATE ...;
BEGIN;
ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;
Hapa hali tayari ni bora, muda wa kusubiri ni mdogo sana. Lakini shida mbili tu zinaharibu uzuri wote:
ALTER TABLE yenyewe inangojea shughuli zingine zote kwenye meza, pamoja na ndefu SELECT
Wakati kichochezi kimezimwa "kuruka na" mabadiliko yoyote mezani, hata yetu. Na haitaingia kwenye hesabu, ingawa inapaswa. Shida!
Kusimamia vigezo vya kikao
Kwa hivyo, katika toleo lililopita, tulijikwaa juu ya jambo la msingi - tunahitaji kwa njia fulani kufundisha kichochezi kutofautisha mabadiliko "yetu" kwenye jedwali kutoka "sio yetu". "Zetu" zimerukwa kama zilivyo, lakini kwa "sio zetu" zinasababishwa. Kwa hili unaweza kutumia vigezo vya kikao.
Utaratibu wa trigger pia huathiriwa na kutofautiana kwa usanidi session_replication_jukumu. Imewashwa bila maagizo ya ziada (chaguo-msingi), vichochezi vitawaka wakati jukumu la urudufishaji ni "asili" (chaguo-msingi) au "ndani". Vichochezi vimewezeshwa kwa kubainisha ENABLE REPLICA, itafanya kazi tu ikiwa hali ya kikao cha sasa - "replica", na vichochezi vimewezeshwa kwa kubainisha ENABLE ALWAYS, itafanya kazi bila kujali hali ya sasa ya urudufishaji.
Nitasisitiza hasa kwamba mpangilio hautumiki kwa wote kwa wakati mmoja, kama ALTER TABLE, lakini tu kwa muunganisho wetu maalum. Kwa jumla, ili hakuna vichochezi vya programu kufanya kazi:
SET session_replication_role = replica; -- Π²ΡΠΊΠ»ΡΡΠΈΠ»ΠΈ ΡΡΠΈΠ³Π³Π΅ΡΡ
UPDATE ...;
SET session_replication_role = DEFAULT; -- Π²Π΅ΡΠ½ΡΠ»ΠΈ Π² ΠΈΡΡ ΠΎΠ΄Π½ΠΎΠ΅ ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅
Hali ndani ya kichochezi
Lakini chaguo hapo juu hufanya kazi kwa vichochezi vyote mara moja (au unahitaji "kubadilisha" vichochezi mapema ambavyo hutaki kuzima). Na ikiwa tunahitaji "zima" kichochezi kimoja maalum?
Majina ya vigezo vya upanuzi yameandikwa kama ifuatavyo: jina la kiendelezi likifuatiwa na nukta na kisha jina la kigezo lenyewe, sawa na majina kamili ya vitu katika SQL. Kwa mfano: plpgsql.variable_conflict.
Kwa sababu chaguo za nje ya mfumo zinaweza kuwekwa katika michakato ambayo haipakii moduli inayofaa ya kiendelezi, PostgreSQL inakubali maadili ya majina yoyote yenye vipengele viwili.
Kwanza, tunakamilisha kichochezi, kitu kama hiki:
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;
...
Kwa njia, hii inaweza kufanyika "kwa faida", bila kuzuia, kupitia CREATE OR REPLACE kwa kazi ya trigger. Na kisha katika unganisho maalum tunacheza "yetu" kutofautisha:
SET mycfg.my_table_convert_process = 'TRUE';
UPDATE ...;
SET mycfg.my_table_convert_process = ''; -- Π²Π΅ΡΠ½ΡΠ»ΠΈ Π² ΠΈΡΡ ΠΎΠ΄Π½ΠΎΠ΅ ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅