Transaksi dalam suatu Transaksi

18

Perilaku apa yang akan ditampilkan PostgreSQL jika misalnya skrip di bawah ini dipanggil

BEGIN;
SELECT * FROM foo;
INSERT INTO foo(name) VALUES ('bar');
BEGIN; <- The point of interest
END;

Apakah PostgreSQL membuang yang kedua BEGINatau akankah sebuah komit diputuskan secara implisit dan kemudian menjalankan BEGIN ENDblokir pada akhirnya sebagai transaksi terpisah?

Alex
sumber

Jawaban:

13

Yang Anda butuhkan adalah apa yang disebut "transaksi otonom" (fitur yang disediakan oleh oracle). Pada titik ini, ini belum memungkinkan di PostgreSQL. Namun, Anda dapat menggunakan SAVEPOINT :

BEGIN;
INSERT ...
SAVEPOINT a;
some error;
ROLLBACK TO SAVEPOINT a;
COMMIT;

Ini bukan sepenuhnya transaksi otonom - tetapi, memungkinkan Anda untuk mendapatkan "setiap transaksi" dengan benar. Anda dapat menggunakannya untuk mencapai hal yang Anda harapkan dari transaksi otonom.

Kalau tidak, tidak ada solusi lain yang masuk akal pada saat ini.

Hans-Jürgen Schönig
sumber
13

Anda bisa mencobanya sendiri:

PERINGATAN: sudah ada transaksi yang sedang berlangsung

Itu tidak memulai (sub) transaksi baru karena transaksi bersarang tidak diimplementasikan dalam PostgreSQL. (Anda dapat melakukan beberapa sihir dalam suatu pl/pgsqlfungsi, misalnya, yang meniru perilaku itu.)

Dengan PostgreSQL 11, orang bisa berpikir prosedur tersimpan nyata baru dan kemampuan mereka untuk menangani transaksi akan memungkinkan transaksi bersarang. Namun, menurut dokumentasi , ini bukan masalahnya:

Dalam prosedur yang dipanggil oleh CALLperintah serta di blok kode anonim ( DOperintah), dimungkinkan untuk mengakhiri transaksi menggunakan perintah COMMITdan ROLLBACK. Transaksi baru dimulai secara otomatis setelah transaksi berakhir menggunakan perintah-perintah ini, sehingga tidak ada perintah START TRANSACTION yang terpisah.

dezso
sumber
9

PostgreSQL tidak mendukung sub-transaksi, tetapi SAVEPOINTfitur ini dapat secara efektif menjawab kebutuhan Anda. Mengutip dari dokumentasi untuk lapisan akses tingkat lanjut ke PG melalui janji-janji oleh Vitaly Tomilov di GitHub:

PostgreSQL tidak memiliki dukungan yang tepat untuk transaksi bersarang, itu hanya mendukung rollback parsial melalui savepoints dalam transaksi. Perbedaan antara kedua teknik ini sangat besar, seperti yang dijelaskan lebih lanjut.

Dukungan yang tepat untuk transaksi bersarang berarti bahwa hasil dari sub-transaksi yang berhasil tidak dibatalkan ketika transaksi induknya dibatalkan. Tetapi dengan PostgreSQL save-points, jika Anda memutar kembali transaksi tingkat atas, hasil dari semua save-points dalam juga dibatalkan.

Savepoints dapat digunakan untuk mengembalikan sebagian ke titik sebelumnya dalam transaksi aktif. Misalnya, untuk membuat savepoint dan kemudian membatalkan efek dari semua perintah yang dieksekusi setelah didirikan:

BEGIN;
    INSERT INTO table1 VALUES (1);
    SAVEPOINT my_savepoint;
    INSERT INTO table1 VALUES (2);
    ROLLBACK TO SAVEPOINT my_savepoint;
    INSERT INTO table1 VALUES (3);
COMMIT;

Transaksi di atas akan memasukkan nilai 1 dan 3, tetapi tidak 2. Lihat SAVEPOINTdokumentasi untuk informasi lebih lanjut.

Amir Ali Akbari
sumber
0

Untuk Postgresql 9.5 atau yang lebih baru, Anda dapat menggunakan pekerja latar belakang dinamis yang disediakan oleh pg_background ekstensi. Ini menciptakan transaksi mandiri. Silakan, lihat halaman github dari ekstensi. Solusi lebih baik daripada db_link. Ada panduan lengkap tentang dukungan transaksi otonom di PostgreSQL

shcherbak
sumber