PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Jalankan pemicu yang ditangguhkan hanya sekali per baris di PostgreSQL

Ini adalah masalah yang rumit. Tapi itu bisa dilakukan dengan pemicu per kolom dan eksekusi pemicu bersyarat yang diperkenalkan di PostgreSQL 9.0 .

Anda memerlukan tanda "diperbarui" per baris untuk solusi ini. Gunakan boolean kolom dalam tabel yang sama untuk kesederhanaan. Tapi bisa juga di tabel lain atau bahkan tabel sementara per transaksi.

Payload mahal dieksekusi sekali per baris di mana penghitung diperbarui (sekali atau beberapa kali).

Ini juga harus melakukan baik, karena ...

  • ... menghindari beberapa panggilan pemicu di root (skala dengan baik)
  • ... tidak mengubah baris tambahan (meminimalkan tabel mengasapi)
  • ... tidak membutuhkan penanganan exception yang mahal.

Perhatikan hal berikut

Demo

Diuji di PostgreSQL 9.1 dengan skema terpisah x sebagai lingkungan pengujian.

Tabel dan baris dummy

-- DROP SCHEMA x;
CREATE SCHEMA x;

CREATE TABLE x.tbl (
 id int
,counter int
,trig_exec_count integer  -- for monitoring payload execution.
,updated bool);

Sisipkan dua baris untuk mendemonstrasikannya berfungsi dengan banyak baris:

INSERT INTO x.tbl VALUES
 (1, 0, 0, NULL)
,(2, 0, 0, NULL);

Fungsi dan Pemicu Pemicu

1.) Jalankan muatan mahal

CREATE OR REPLACE FUNCTION x.trg_upaft_counter_change_1()
    RETURNS trigger AS
$BODY$
BEGIN

 -- PERFORM some_expensive_procedure(NEW.id);
 -- Update trig_exec_count to count execution of expensive payload.
 -- Could be in another table, for simplicity, I use the same:

UPDATE x.tbl t
SET    trig_exec_count = trig_exec_count + 1
WHERE  t.id = NEW.id;

RETURN NULL;  -- RETURN value of AFTER trigger is ignored anyway

END;
$BODY$ LANGUAGE plpgsql;

2.) Tandai baris sebagai diperbarui.

CREATE OR REPLACE FUNCTION x.trg_upaft_counter_change_2()
    RETURNS trigger AS
$BODY$
BEGIN

UPDATE x.tbl
SET    updated = TRUE
WHERE  id = NEW.id;
RETURN NULL;

END;
$BODY$ LANGUAGE plpgsql;

3.) Setel ulang tanda "diperbarui".

CREATE OR REPLACE FUNCTION x.trg_upaft_counter_change_3()
    RETURNS trigger AS
$BODY$
BEGIN

UPDATE x.tbl
SET    updated = NULL
WHERE  id = NEW.id;
RETURN NULL;

END;
$BODY$ LANGUAGE plpgsql;

Nama pemicu relevan! Dipanggil untuk acara yang sama, mereka dieksekusi dalam urutan abjad.

1.) Payload, hanya jika belum "diperbarui":

CREATE CONSTRAINT TRIGGER upaft_counter_change_1
    AFTER UPDATE OF counter ON x.tbl
    DEFERRABLE INITIALLY DEFERRED
    FOR EACH ROW
    WHEN (NEW.updated IS NULL)
    EXECUTE PROCEDURE x.trg_upaft_counter_change_1();

2.) Tandai baris sebagai diperbarui, hanya jika belum "diperbarui":

CREATE TRIGGER upaft_counter_change_2   -- not deferred!
    AFTER UPDATE OF counter ON x.tbl
    FOR EACH ROW
    WHEN (NEW.updated IS NULL)
    EXECUTE PROCEDURE x.trg_upaft_counter_change_2();

3.) Atur Ulang Bendera. Tidak ada pengulangan tanpa akhir karena kondisi pemicu.

CREATE CONSTRAINT TRIGGER upaft_counter_change_3
    AFTER UPDATE OF updated ON x.tbl
    DEFERRABLE INITIALLY DEFERRED
    FOR EACH ROW
    WHEN (NEW.updated)                 --
    EXECUTE PROCEDURE x.trg_upaft_counter_change_3();

Uji

Jalankan UPDATE &SELECT secara terpisah untuk melihat efek yang ditangguhkan. Jika dieksekusi bersama (dalam satu transaksi) SELECT akan menampilkan tbl.counter . yang baru tapi tbl2.trig_exec_count yang lama .

UPDATE x.tbl SET counter = counter + 1;

SELECT * FROM x.tbl;

Sekarang, perbarui penghitung beberapa kali (dalam satu transaksi). Payload hanya akan dieksekusi sekali. Voilá!

UPDATE x.tbl SET counter = counter + 1;
UPDATE x.tbl SET counter = counter + 1;
UPDATE x.tbl SET counter = counter + 1;
UPDATE x.tbl SET counter = counter + 1;
UPDATE x.tbl SET counter = counter + 1;

SELECT * FROM x.tbl;


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SETELAH LOGON(Oracle) memicu di PostgreSQL dengan ekstensi – login_hook

  2. Meningkatkan ke PostgreSQL13

  3. Menyiapkan Lingkungan Optimal untuk PostgreSQL

  4. Ikhtisar PostgreSQL Query Caching &Load Balancing

  5. Bagaimana cara mengimpor modul atau menginstal ekstensi di Postgres?