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

Pemicu acara ROLLBACK di postgresql

Anda tidak dapat menggunakan urutan untuk ini. Anda memerlukan satu titik serialisasi yang melaluinya semua sisipan harus pergi - jika tidak, atribut "tanpa celah" tidak dapat dijamin. Anda juga perlu memastikan bahwa tidak ada baris yang akan dihapus dari tabel itu.

Serialisasi juga berarti bahwa hanya satu transaksi yang dapat menyisipkan baris ke dalam tabel itu - semua sisipan lainnya harus menunggu hingga sisipan "sebelumnya" telah dikomit atau dibatalkan.

Salah satu pola bagaimana ini dapat diimplementasikan adalah memiliki tabel tempat nomor "urutan" disimpan. Mari kita asumsikan kita membutuhkan ini untuk nomor faktur yang harus tanpa celah karena alasan hukum.

Jadi pertama-tama kita buat tabel untuk menampung "nilai saat ini":

create table slow_sequence 
(
  seq_name        varchar(100) not null primary key,
  current_value   integer not null default 0
);

-- create a "sequence" for invoices
insert into slow_sequence values ('invoice');

Sekarang kita membutuhkan fungsi yang akan menghasilkan nomor berikutnya tetapi itu menjamin bahwa tidak ada dua transaksi yang dapat memperoleh nomor berikutnya secara bersamaan.

create or replace function next_number(p_seq_name text)
  returns integer
as
$$
  update slow_sequence
     set current_value = current_value + 1
  where seq_name = p_seq_name
  returning current_value;
$$
language sql;

Fungsi akan menambah penghitung dan mengembalikan nilai yang bertambah sebagai hasilnya. Karena update baris untuk urutan sekarang terkunci dan tidak ada transaksi lain yang dapat memperbarui nilai itu. Jika transaksi panggilan dibatalkan, begitu juga pembaruan ke penghitung urutan. Jika di-commit, nilai baru akan tetap ada.

Untuk memastikan bahwa setiap transaksi menggunakan fungsi, pemicu harus dibuat.

Buat tabel yang dimaksud:

create table invoice 
(
  invoice_number integer not null primary key, 
  customer_id    integer not null,
  due_date       date not null
);

Sekarang buat fungsi pemicu dan pemicu:

create or replace function f_invoice_trigger()
  returns trigger
as
$$
begin
  -- the number is assigned unconditionally so that this can't 
  -- be prevented by supplying a specific number
  new.invoice_number := next_number('invoice');
  return new;
end;
$$
language plpgsql;

create trigger invoice_trigger
  before insert on invoice
  for each row
  execute procedure f_invoice_trigger();

Sekarang jika satu transaksi melakukan ini:

insert into invoice (customer_id, due_date) 
values (42, date '2015-12-01');

Nomor baru dihasilkan. detik transaksi kemudian perlu menunggu hingga penyisipan pertama dilakukan atau dibatalkan.

Seperti yang saya katakan:solusi ini tidak terukur. Tidak semuanya. Ini akan memperlambat aplikasi Anda secara besar-besaran jika ada banyak sisipan ke dalam tabel itu. Tetapi Anda tidak dapat memiliki keduanya:dan . yang skalabel implementasi yang benar dari urutan tanpa celah.

Saya juga cukup yakin bahwa ada kasus tepi yang tidak tercakup oleh kode di atas. Jadi kemungkinan besar Anda masih bisa menemukan celah.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cara Mengembalikan Hasil Kueri sebagai Daftar Dipisahkan Koma di PostgreSQL

  2. Tidak dapat menemukan header 'libpq-fe.h saat mencoba menginstal pg gem

  3. Menyimpan Gambar di PostgreSQL

  4. Impor Data Excel ke PostgreSQL 9.3

  5. Apakah INSERT RETURNING dijamin untuk mengembalikan barang dalam urutan yang benar?