PostgreSQL ಆಂಟಿಪ್ಯಾಟರ್ನ್ಸ್: ಪ್ರಚೋದಕವನ್ನು ಬೈಪಾಸ್ ಮಾಡುವ ಡೇಟಾವನ್ನು ಬದಲಾಯಿಸಿ

ಶೀಘ್ರದಲ್ಲೇ ಅಥವಾ ನಂತರ, ಟೇಬಲ್ ದಾಖಲೆಗಳಲ್ಲಿ ಏನನ್ನಾದರೂ ಬೃಹತ್ ಪ್ರಮಾಣದಲ್ಲಿ ಸರಿಪಡಿಸುವ ಅಗತ್ಯವನ್ನು ಅನೇಕ ಜನರು ಎದುರಿಸುತ್ತಾರೆ. ನಾನು ಈಗಾಗಲೇ ಅದನ್ನು ಹೇಗೆ ಉತ್ತಮವಾಗಿ ಮಾಡಬೇಕೆಂದು ನನಗೆ ಹೇಳಿದರು, ಮತ್ತು ಹೇಗೆ - ಅದನ್ನು ಮಾಡದಿರುವುದು ಉತ್ತಮ. ಇಂದು ನಾನು ಸಾಮೂಹಿಕ ನವೀಕರಣದ ಎರಡನೇ ಅಂಶದ ಬಗ್ಗೆ ಮಾತನಾಡುತ್ತೇನೆ - ಪ್ರಚೋದಕಗಳ ಬಗ್ಗೆ.

ಉದಾಹರಣೆಗೆ, ನೀವು ಏನನ್ನಾದರೂ ಸರಿಪಡಿಸಬೇಕಾದ ಮೇಜಿನ ಮೇಲೆ, ದುಷ್ಟ ಪ್ರಚೋದಕವಿದೆ 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
  • ಟ್ರಿಗರ್ ಆಫ್ ಆಗಿರುವಾಗ, ಯಾವುದೇ ಬದಲಾವಣೆಯು "ಹಾರಿಹೋಗುತ್ತದೆ" ಕೋಷ್ಟಕದಲ್ಲಿ, ನಮ್ಮದಲ್ಲ. ಮತ್ತು ಅದು ಘಟಕಗಳಿಗೆ ಪ್ರವೇಶಿಸುವುದಿಲ್ಲ, ಆದರೂ ಅದು ಇರಬೇಕು. ತೊಂದರೆ!

ಸೆಷನ್ ವೇರಿಯಬಲ್‌ಗಳನ್ನು ನಿರ್ವಹಿಸುವುದು

ಆದ್ದರಿಂದ, ಹಿಂದಿನ ಆವೃತ್ತಿಯಲ್ಲಿ ನಾವು ಒಂದು ಮೂಲಭೂತ ಅಂಶವನ್ನು ಕಂಡಿದ್ದೇವೆ - ಟೇಬಲ್‌ನಲ್ಲಿನ “ನಮ್ಮ” ಬದಲಾವಣೆಗಳನ್ನು “ನಮ್ಮದಲ್ಲ” ಯಿಂದ ಪ್ರತ್ಯೇಕಿಸಲು ನಾವು ಹೇಗಾದರೂ ಪ್ರಚೋದಕವನ್ನು ಕಲಿಸಬೇಕಾಗಿದೆ. "ನಮ್ಮದು" ಅನ್ನು ಬಿಟ್ಟುಬಿಡಲಾಗಿದೆ ಮತ್ತು "ನಮ್ಮದಲ್ಲ" ಎಂದು ಪ್ರಚೋದಿಸಲಾಗಿದೆ. ಇದಕ್ಕಾಗಿ ನೀವು ಬಳಸಬಹುದು ಅಧಿವೇಶನ ಅಸ್ಥಿರ.

ಅಧಿವೇಶನ_ಪ್ರತಿಕೃತಿ_ಪಾತ್ರ

ಓದಿ ಕೈಪಿಡಿ:

ಪ್ರಚೋದಕ ಕಾರ್ಯವಿಧಾನವು ಕಾನ್ಫಿಗರೇಶನ್ ವೇರಿಯಬಲ್‌ನಿಂದ ಪ್ರಭಾವಿತವಾಗಿರುತ್ತದೆ ಅಧಿವೇಶನ_ಪ್ರತಿಕೃತಿ_ಪಾತ್ರ. ಹೆಚ್ಚಿನ ಸೂಚನೆಗಳಿಲ್ಲದೆ (ಡೀಫಾಲ್ಟ್) ಸಕ್ರಿಯಗೊಳಿಸಿದಾಗ, ಪ್ರತಿಕೃತಿ ಪಾತ್ರವು "ಮೂಲ" (ಡೀಫಾಲ್ಟ್) ಅಥವಾ "ಸ್ಥಳೀಯ" ಆಗಿರುವಾಗ ಟ್ರಿಗ್ಗರ್‌ಗಳು ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತವೆ. ಸೂಚನೆಗಳ ಮೂಲಕ ಟ್ರಿಗ್ಗರ್‌ಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ ENABLE 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 = ''; -- вернули в исходное состояние

ನಿಮಗೆ ಇತರ ಮಾರ್ಗಗಳು ತಿಳಿದಿದೆಯೇ? ಕಾಮೆಂಟ್‌ಗಳಲ್ಲಿ ಹಂಚಿಕೊಳ್ಳಿ.

ಮೂಲ: www.habr.com

ಕಾಮೆಂಟ್ ಅನ್ನು ಸೇರಿಸಿ