PostgreSQL Antipatterns: промСнямС Π΄Π°Π½Π½ΠΈ заобикаляйки Ρ‚Ρ€ΠΈΠ³Π΅Ρ€Π°

Π Π°Π½ΠΎ ΠΈΠ»ΠΈ късно ΠΌΠ½ΠΎΠ³ΠΎ Ρ…ΠΎΡ€Π° сС ΡΠ±Π»ΡŠΡΠΊΠ²Π°Ρ‚ с нСобходимостта ΠΎΡ‚ масови ΠΊΠΎΡ€Π΅ΠΊΡ†ΠΈΠΈ Π² записитС Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Π°. Аз Π²Π΅Ρ‡Π΅ Ρ€Π°Π·ΠΊΠ°Π·Π²Π°Ρ… ΠΊΠ°ΠΊ Π΄Π° Π³ΠΎ Π½Π°ΠΏΡ€Π°Π²ΠΈΠΌ ΠΏΠΎ-Π΄ΠΎΠ±Ρ€Π΅, Π° ΠΊΠ°ΠΊ β€” ΠΏΠΎ-Π΄ΠΎΠ±Ρ€Π΅ Π΄Π° Π½Π΅ Π³ΠΎ ΠΏΡ€Π°Π²ΠΈΠΌ. ДнСс Ρ‰Π΅ говоря Π·Π° втория аспСкт Π½Π° масовото ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ β€” Π·Π° задСйстванСто Π½Π° Ρ‚Ρ€ΠΈΠ³Π΅Ρ€ΠΈ.

НапримСр, Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π°, Π² която трябва Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈΡ‚Π΅ Π½Π΅Ρ‰ΠΎ, ΠΈΠΌΠ° Π·Π»ΠΎΠ½Π°ΠΌΠ΅Ρ€Π΅Π½ Ρ‚Ρ€ΠΈΠ³Π΅Ρ€ ON UPDATE, ΠΊΠΎΠΉΡ‚ΠΎ прСнася всички измСнСния Π² някакви Π°Π³Ρ€Π΅Π³Π°Ρ‚ΠΈ. А Π½Π° вас Π²ΠΈ трябва Π΄Π° ΠΎΠ±Π½ΠΎΠ²ΠΈΡ‚Π΅ всичко (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π΄Π° ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€Π°Ρ‚Π΅ Π½ΠΎΠ²ΠΎ ΠΏΠΎΠ»Π΅) Ρ‚Π°ΠΊΠ° Π²Π½ΠΈΠΌΠ°Ρ‚Π΅Π»Π½ΠΎ, Ρ‡Π΅ Ρ‚Π΅Π·ΠΈ Π°Π³Ρ€Π΅Π³Π°Ρ‚ΠΈ Π΄Π° Π½Π΅ Π±ΡŠΠ΄Π°Ρ‚ засСгнати.

НСка просто Π΄Π΅Π°ΠΊΡ‚ΠΈΠ²ΠΈΡ€Π°ΠΌΠ΅ Ρ‚Ρ€ΠΈΠ³Π΅Ρ€ΠΈΡ‚Π΅!

BEGIN;
  ALTER TABLE ... DISABLE TRIGGER ...;
  UPDATE ...; -- Ρ‚ΡƒΠΊ Ρ‡Π°ΠΊΠ°Π½Π΅
  ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;

БобствСно, Ρ‚ΠΎΠ²Π° Π΅ всичко β€” всичко Π²Π΅Ρ‡Π΅ Π΅ Π°ΠΊΡ‚ΠΈΠ²ΠΈΡ€Π°Π½ΠΎ.

Π—Π°Ρ‰ΠΎΡ‚ΠΎ ALTER TABLE Π½Π°Π»Π°Π³Π° AccessExclusive-Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ°, ΠΏΠΎΠ΄ която Π½ΠΈΠΊΠΎΠΉ ΠΏΠ°Ρ€Π°Π»Π΅Π»Π½ΠΎ ΠΈΠ·ΠΏΡŠΠ»Π½ΡΠ²Π°Ρ‰ сС, Π΄ΠΎΡ€ΠΈ прост SELECT, Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΏΡ€ΠΎΡ‡Π΅Ρ‚Π΅ Π½ΠΈΡ‰ΠΎ ΠΎΡ‚ Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π°. ВоСст, Π΄ΠΎΠΊΠ°Ρ‚ΠΎ Ρ‚Π°Π·ΠΈ транзакция Π½Π΅ Π·Π°Π²ΡŠΡ€ΡˆΠΈ, всички ΠΆΠ΅Π»Π°Π΅Ρ‰ΠΈ Π΄ΠΎΡ€ΠΈ β€žΠΏΡ€ΠΎΡΡ‚ΠΎ Π΄Π° ΠΏΡ€ΠΎΡ‡Π΅Ρ‚Π°Ρ‚β€œ Ρ‰Π΅ Ρ‡Π°ΠΊΠ°Ρ‚. А Π½ΠΈΠ΅ ΠΏΠΎΠΌΠ½ΠΈΠΌ, Ρ‡Π΅ UPDATE ΠΈΠΌΠ°ΠΌΠ΅ дълго...

НСка Ρ‚ΠΎΠ³Π°Π²Π° Π±ΡŠΡ€Π·ΠΎ Π΄Π΅Π°ΠΊΡ‚ΠΈΠ²ΠΈΡ€Π°ΠΌΠ΅, послС Π±ΡŠΡ€Π·ΠΎ Π°ΠΊΡ‚ΠΈΠ²ΠΈΡ€Π°ΠΌΠ΅!

BEGIN;
  ALTER TABLE ... DISABLE TRIGGER ...;
COMMIT;

UPDATE ...;

BEGIN;
  ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;

Π’ΡƒΠΊ ситуацията Π²Π΅Ρ‡Π΅ Π΅ ΠΏΠΎ-Π΄ΠΎΠ±Ρ€Π°, Π²Ρ€Π΅ΠΌΠ΅Ρ‚ΠΎ Π½Π° ΠΈΠ·Ρ‡Π°ΠΊΠ²Π°Π½Π΅ Π΅ Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»Π½ΠΎ ΠΏΠΎ-ΠΌΠ°Π»ΠΊΠΎ. Но Π΄Π²Π΅ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° развалят цялата красота:

  • ALTER TABLE ΡΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° Ρ‡Π°ΠΊΠ° всички Π΄Ρ€ΡƒΠ³ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π°, Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»Π½ΠΎ Π΄ΡŠΠ»Π³ΠΈΡ‚Π΅ SELECT
  • Π”ΠΎΠΊΠ°Ρ‚ΠΎ Ρ‚Ρ€ΠΈΠ³Π΅Ρ€ΡŠΡ‚ Π΅ ΠΈΠ·ΠΊΠ»ΡŽΡ‡Π΅Π½, всяка промяна Π² Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π°, Π΄ΠΎΡ€ΠΈ ΠΈ Π½Π΅ наша, Ρ‰Π΅ "пролСтя" ΠΏΠΎΠΊΡ€Π°ΠΉ Π½Π΅Π³ΠΎ. И Π² Π°Π³Ρ€Π΅Π³Π°Ρ‚ΠΈΡ‚Π΅ Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΏΠΎΠΏΠ°Π΄Π°, Π²ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‡Π΅ трябва. ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌ!

Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½Π° сСсийнитС ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ

И Ρ‚Π°ΠΊΠ°, Π² ΠΏΡ€Π΅Π΄ΠΈΡˆΠ½ΠΈΡ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ ΠΏΠΎΠΏΠ°Π΄Π½Π°Ρ…ΠΌΠ΅ Π½Π° ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠ΅Π½ ΠΌΠΎΠΌΠ΅Π½Ρ‚ β€” трябва ΠΏΠΎ някакъв Π½Π°Ρ‡ΠΈΠ½ Π΄Π° Π½Π°ΡƒΡ‡ΠΈΠΌ Ρ‚Ρ€ΠΈΠ³Π΅Ρ€Π° Π΄Π° Ρ€Π°Π·Π»ΠΈΡ‡Π°Π²Π° "Π½Π°ΡˆΠΈΡ‚Π΅" ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈ Π² Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π° ΠΎΡ‚ "Π½Π΅ Π½Π°ΡˆΠΈΡ‚Π΅". "ΠΠ°ΡˆΠΈΡ‚Π΅" Π΄Π° пропускат, Π° "Π½Π΅ Π½Π°ΡˆΠΈΡ‚Π΅" β€” Π΄Π° задСйстват. Π—Π° Ρ‚ΠΎΠ²Π° ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ сСсийни ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ.

session_replication_role

Π§Π΅Ρ‚Π΅ΠΌ Π½Π°Ρ€ΡŠΡ‡Π½ΠΈΠΊ:

На ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠ° Π½Π° задСйстванС Π½Π° Ρ‚Ρ€ΠΈΠ³Π΅Ρ€ΠΈΡ‚Π΅ ΡΡŠΡ‰ΠΎ влияС ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΎΠ½Π½Π°Ρ‚Π° ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²Π° session_replication_role. Π’ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ‚Π΅ Π±Π΅Π· Π΄ΠΎΠΏΡŠΠ»Π½ΠΈΡ‚Π΅Π»Π½ΠΈ указания (ΠΏΠΎ ΠΏΠΎΠ΄Ρ€Π°Π·Π±ΠΈΡ€Π°Π½Π΅) Ρ‚Ρ€ΠΈΠ³Π΅Ρ€ΠΈ Ρ‰Π΅ сС задСйстват, ΠΊΠΎΠ³Π°Ρ‚ΠΎ роля Π½Π° рСпликация β€” "origin" (ΠΏΠΎ ΠΏΠΎΠ΄Ρ€Π°Π·Π±ΠΈΡ€Π°Π½Π΅) ΠΈΠ»ΠΈ "local". Π’Ρ€ΠΈΠ³Π΅Ρ€ΠΈ, Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈ с ΡƒΠΊΠ°Π·Π°Π½ΠΈΠ΅Ρ‚ΠΎ ENABLE REPLICA, Ρ‰Π΅ сС задСйстват само Π°ΠΊΠΎ тСкущият Ρ€Π΅ΠΆΠΈΠΌ Π½Π° сСсията Π΅ "replica", Π° Ρ‚Ρ€ΠΈΠ³Π΅Ρ€ΠΈ, Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈ с ΡƒΠΊΠ°Π·Π°Π½ΠΈΠ΅Ρ‚ΠΎ ENABLE ALWAYS, Ρ‰Π΅ сС задСйстват нСзависимо ΠΎΡ‚ тСкущия Ρ€Π΅ΠΆΠΈΠΌ Π½Π° рСпликация.

ОсобСно ΠΏΠΎΠ΄Ρ‡Π΅Ρ€Ρ‚Π°Π²Π°ΠΌ, Ρ‡Π΅ настройката сС отнася Π½Π΅ само Π΄ΠΎ всички-всички Π²Π΅Π΄Π½Π°Π³Π°, ΠΊΠ°ΠΊΡ‚ΠΎ ALTER TABLE, Π° само към нашия ΠΎΡ‚Π΄Π΅Π»Π΅Π½ спСциалСн ΠΊΠΎΠ½Π΅ΠΊΡ‚ΠΎΡ€. Π’Π°ΠΊΠ° Ρ‡Π΅, Π·Π° Π΄Π° Π½Π΅ сработват Π½ΠΈΠΊΠ°ΠΊΠ²ΠΈ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ½ΠΈ Ρ‚Ρ€ΠΈΠ³Π΅Ρ€ΠΈ:

SET session_replication_role = replica; -- ΠΈΠ·ΠΊΠ»ΡŽΡ‡ΠΈΡ…ΠΌΠ΅ Ρ‚Ρ€ΠΈΠ³Π΅Ρ€ΠΈΡ‚Π΅
UPDATE ...;
SET session_replication_role = DEFAULT; -- Π²ΡŠΡ€Π½Π°Ρ…ΠΌΠ΅ Π² ΠΏΡŠΡ€Π²ΠΎΠ½Π°Ρ‡Π°Π»Π½ΠΎ ΡΡŠΡΡ‚ΠΎΡΠ½ΠΈΠ΅

УсловиСто Π² Ρ‚Ρ€ΠΈΠ³Π΅Ρ€Π°

Но ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½Π°Ρ‚Π° ΠΏΠΎ-Π³ΠΎΡ€Π΅ вСрсия Ρ€Π°Π±ΠΎΡ‚ΠΈ Π·Π° всички Ρ‚Ρ€ΠΈΠ³Π΅Ρ€ΠΈ навСднъТ (ΠΈΠ»ΠΈ трябва Π΄Π° β€žΠ°Π»Ρ‚Π΅Ρ€Π½Π΅Ρ‚Π΅β€œ ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»Π½ΠΎ Ρ‚Ρ€ΠΈΠ³Π΅Ρ€ΠΈΡ‚Π΅, ΠΊΠΎΠΈΡ‚ΠΎ Π½Π΅ искатС Π΄Π° Π΄Π΅Π°ΠΊΡ‚ΠΈΠ²ΠΈΡ€Π°Ρ‚Π΅). А Π°ΠΊΠΎ трябва Π΄Π° β€žΠΈΠ·ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅β€œ Π΅Π΄ΠΈΠ½ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π΅Π½ Ρ‚Ρ€ΠΈΠ³Π΅Ρ€?

Π’ Ρ‚ΠΎΠ²Π° Ρ‰Π΅ Π½ΠΈ ΠΏΠΎΠΌΠΎΠ³Π½Π΅ пСрсонализирана сСсийна ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²Π°:

Π˜ΠΌΠ΅Π½Π°Ρ‚Π° Π½Π° ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈΡ‚Π΅ Π½Π° Ρ€Π°Π·ΡˆΠΈΡ€Π΅Π½ΠΈΡΡ‚Π° сС записват ΠΏΠΎ слСдния Π½Π°Ρ‡ΠΈΠ½: ΠΈΠΌΠ΅ Π½Π° Ρ€Π°Π·ΡˆΠΈΡ€Π΅Π½ΠΈΠ΅, Ρ‚ΠΎΡ‡ΠΊΠ° ΠΈ слСд Ρ‚ΠΎΠ²Π° собствСно ΠΈΠΌΠ΅ Π½Π° ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚ΡŠΡ€Π°, ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎ Π½Π° ΠΏΡŠΠ»Π½ΠΈΡ‚Π΅ ΠΈΠΌΠ΅Π½Π° Π½Π° ΠΎΠ±Π΅ΠΊΡ‚ΠΈ Π² SQL. НапримСр: plpgsql.variable_conflict.
Въй ΠΊΠ°Ρ‚ΠΎ нСсистСмнитС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ Π·Π°Π΄Π°Π΄Π΅Π½ΠΈ Π² процСси, ΠΊΠΎΠΈΡ‚ΠΎ Π½Π΅ Π·Π°Ρ€Π΅ΠΆΠ΄Π°Ρ‚ ΡΡŠΠΎΡ‚Π²Π΅Ρ‚Π½ΠΈΡ ΠΌΠΎΠ΄ΡƒΠ» Π½Π° Ρ€Π°Π·ΡˆΠΈΡ€Π΅Π½ΠΈΠ΅Ρ‚ΠΎ, PostgreSQL ΠΏΡ€ΠΈΠ΅ΠΌΠ° стойности Π·Π° всякакви ΠΈΠΌΠ΅Π½Π° с Π΄Π²Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΈ.

ΠŸΡŠΡ€Π²ΠΎ Π΄ΠΎΡ€Π°Π±ΠΎΡ‚Π²Π°ΠΌΠ΅ Ρ‚Ρ€ΠΈΠ³Π΅Ρ€Π°, Π΅Ρ‚ΠΎ ΠΊΠ°ΠΊ:

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;
...

ΠœΠ΅ΠΆΠ΄Ρƒ Π΄Ρ€ΡƒΠ³ΠΎΡ‚ΠΎ, Ρ‚ΠΎΠ²Π° ΠΌΠΎΠΆΠ΅ Π΄Π° сС Π½Π°ΠΏΡ€Π°Π²ΠΈ β€žΠ½Π°ΠΆΠΈΠ²ΠΎβ€œ, Π±Π΅Π· Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ, Ρ‡Ρ€Π΅Π· CREATE OR REPLACE Π·Π° Ρ‚Ρ€ΠΈΠ³Π΅Ρ€Π½Π°Ρ‚Π° функция. А слСд Ρ‚ΠΎΠ²Π° Π² спСциалния ΠΊΠΎΠ½Π΅ΠΊΡ‚ΠΎΡ€ Π·Π°Π΄Π°Π²Π°ΠΌΠ΅ β€žΠ½Π°ΡˆΠ°Ρ‚Π°β€œ ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²Π°:


SET mycfg.my_table_convert_process = 'TRUE';
UPDATE ...;
SET mycfg.my_table_convert_process = ''; -- Π²ΡŠΡ€Π½Π°Ρ…ΠΌΠ΅ Π² ΠΏΡŠΡ€Π²ΠΎΠ½Π°Ρ‡Π°Π»Π½ΠΎ ΡΡŠΡΡ‚ΠΎΡΠ½ΠΈΠ΅

Π—Π½Π°Π΅Ρ‚Π΅ Π»ΠΈ Π΄Ρ€ΡƒΠ³ΠΈ Π½Π°Ρ‡ΠΈΠ½ΠΈ? Π‘ΠΏΠΎΠ΄Π΅Π»Π΅Ρ‚Π΅ Π² ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΡ‚Π΅.

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com

ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС със Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS ΠΈ VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ πŸ”₯ ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС със Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS ΠΈ VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ | ProHoster