Interaksi PL/SQL dengan Oracle

6.8.5. Bagaimana Oracle Melakukan Implicit Rollbacks

Sebelum mengeksekusi perintah INSERT, UPDATE, atau DELETE, Oracle menandai savepoint implisit (tidak tersedia bagi kita). Jika perintah tersebut gagal, Oracle melakukan roll back ke savepoint tersebut. Secara normal, hanya perintah SQL yang gagal saja yang di-rollback, bukan keseluruhan transaksi. Namun, jika suatu perintah menyebabkan munculnya unhandled exception, host environment akan menentukan apa yang akan di-rollback.

6.8.6. Mengakhiri Transaksi

Praktek pemrograman yang baik adalah dengan melakukan commit atau rollback terhadap setiap transaksi secara eksplisit. Apakah kita melakukan commit atau rollback di dalam program  PL/SQL atau dalam host enviroment bergantung kepada aliran logika aplikasi kita. Jika kita mengabaikan commit atau rollback sebuah transaksi secara eksplisit, host environment menentukan keadaan akhirnya.

Sebagai contoh, dalam lingkungan SQL*Plus, jika blok PL/SQL tidak menyertakan perintah COMMIT atau ROLLBACK, keadaan akhir dari transaksi kita bergantung pada apa yang kita kerjakan setelah menjalankan suatu blok. Jika kita mengeksekusi perintah data definition, data control, atau COMMIT atau jika kita mengetikkan perintah EXIT, DISCONNECT, atau QUIT, Oracle meng-commit transaksi. Jika kita mengeksekusi perintah ROLLBACK atau menggagalkan session SQL*Plus, Oracle me-rollback transaksi.

Dalam lingkungan Oracle Precompiler, jika program kita tidak berakhir secara normal, Oracle me-rollback transaksi. Program berakhir secara normal ketika ia secara eksplisit melakukan commit atau rollback pekerjaan dan keluar dari Oracle dengan menggunakan parameter RELEASE, seperti berikut:

EXEC SQL COMMIT WORK RELEASE;

6.8.7. Mengatur Properti Transaksi dengan SET TRANSACTION

Kita menggunakan perintah SET TRANSACTION untuk memulai transaksi read-only atau read-write, menetapkan level isolasi, atau menempatkan transaksi terkini ke rollback segment tertentu. Transaksi-transaksi read-only berguna untuk menjalankan banyak query terhadap satu atau lebih table-table ketika pengguna-pengguna lain meng-update table-table yang sama.

Selama transaksi read-only, seluruh query mengacu kepada snapshot yang sama dari database, menyediakan view multi-table, multi-query, dan read-consistent. Pengguna-pengguna lain dapat melanjutkan query atau melakukan update data seperti biasa.

Commit atau rollback mengakhiri transaksi. Dalam contoh di bawah ini, sebagai manajer toko, kita menggunakan transaksi read-only untuk mendapatkan gambaran penjualan untuk suatu hari, minggu sebelumnya, dan bulan sebelumnya. Gambaran-gambaran tersebut tidak terpengaruh oleh pengguna-pengguna lain yang sedang melakukan update database selama transaksi.

DECLARE
  daily_sales REAL;
  weekly_sales REAL;
  monthly_sales REAL;
BEGIN
  ...
  COMMIT; -- mengakhiri transaksi sebelumnya
  SET TRANSACTION READ ONLY NAME 'Calculate sales figures';
  SELECT SUM(amt)
  INTO daily_sales
  FROM sales
  WHERE dte = SYSDATE;
  SELECT SUM(amt)
  INTO weekly_sales
  FROM sales
  WHERE dte > SYSDATE - 7;
  SELECT SUM(amt)
  INTO monthly_sales
  FROM sales
  WHERE dte > SYSDATE - 30;
  COMMIT; -- mengakhiri transaksi read-only
  ...
END;

Perintah SET TRANSACTION harus menjadi perintah SQL pertama dalam transaksi read-only dan hanya dapat muncul sekali dalam transaksi. Jika kita mengatur transaksi untuk menjadi READ ONLY, query-query selanjutnya hanya melihat perubahan-perubahan yang di-commit sebelum transaksi dimulai. Penggunaan READ ONLY tidak mempengaruhi pengguna-pengguna atau transaksi-transaksi lain.

6.8.7.1. Batasan-batasan pada SET TRANSACTION

Hanya perintah-perintah SELECT INTO, OPEN, FETCH, CLOSE, LOCK TABLE, COMMIT, and ROLLBACK yang diperbolehkan di dalam transaksi read-only. Juga, query-query tidak dapat menjadi FOR UPDATE.

6.8.8. Mengesampingkan Default Locking

Secara default, Oracle mengunci struktur-struktur data untuk kita secara otomatis. Namun, kita dapat meminta penguncian-penguncian tertentu terhadap data atau table-table ketika menguntungkan bagi kita untuk mengesampingkan penguncian default. Penguncian eksplisit mengijinkan kita untuk berbagi atau meniadakan akses ke table untuk satu waktu tertentu saat transaksi.

Dengan perintah LOCK TABLE, kita dapat mengunci seluruh table-table secara eksplisit. Dengan perintah SELECT FOR UPDATE, kita dapat secara eksplisit mengunci baris-baris data tertentu pada table untuk meyakinkan bahwa mereka tidak berubah sebelum pengubahan atau penghapusan dieksekusi. Namun, Oracle secara otomatis menghasilkan penguncian row-level pada saat pengubahan atau penghapusan. Jadi, gunakan klausa FOR UPDATE hanya jika kita intin mengunci baris-baris data sebelum pengubahan atau penghapusan.

6.8.8.1. Menggunakan FOR UPDATE

Ketika kita mendeklarasikan cursor yang akan direferensi dalam klausa CURRENT OF dari perintah UPDATE atau DELETE, kita harus menggunakan klausa FOR UPDATE untuk memperoleh penguncian-penguncian baris data secara eksklusif. Contohnya adalah sebagai berikut:

DECLARE
  CURSOR c1 IS
    SELECT empno, sal
    FROM emp
    WHERE job = 'SALESMAN' AND comm > sal
    FOR UPDATE NOWAIT;

Perintah SELECT …FOR UPDATE mengidentifikasi baris-baris data yang akan diubah atau dihapus, kemudian mengunci baris data dalam result set. Hal ini berguna ketika kita ingin mendasarkan pengubahan pada nilai-nilai yang telah ada pada baris data. Dalam kasus tersebut, kita harus meyakinkan bahwa baris data tidak diubah oleh pengguna lain sebelum proses update.

Keyword opsional NOWAIT memberitahukan Oracle untuk tidak menunggu jika baris-baris data yang diminta telah dikunci oleh pengguna lain. Kontrol segera dikembalikan ke program kita sehingga ia dapat melakukan perkerjaan lain sebelum mencoba lagi untuk mendapatkan penguncian. Jika kita mengabaikan keyword NOWAIT, Oracle menunggu sampai baris-baris data tersebut tersedia.

Seluruh baris-baris data dikunci ketika kita membuka cursor, tidak ketika mereka di-fetch. Baris-baris data dibuka pengunciannya ketika kita melakukan commit atau rollback terhadap transaksi. Jadi, kita tidak dapat melakukan fetch dari cursor FOR UPDATE setelah commit.

Ketika melakukan query terhadap banyak table, kita dapat menggunakan klausa FOR UPDATE untuk membatasi penguncian baris data terhadap table-table tertentu. Baris-baris data dalam table dikunci hanya jika klausa FOR UPDATE OF mengacu kepada kolom dalam table tersebut. Sebagai contoh, query berikut mengunci baris-baris data pada table emp namun tidak pada table dept:

DECLARE
  CURSOR c1 IS
    SELECT ename, dname
    FROM emp, dept
    WHERE emp.deptno = dept.deptno AND job = 'MANAGER'
    FOR UPDATE OF sal;

Seperti ditunjukkan oleh contoh selanjutnya, kita menggunakan klausa CURRENT OF pada perintah UPDATE atau DELETE untuk mengacu kepada baris data terakhir yang di-fetch dari sebuah cursor:

DECLARE
  CURSOR c1 IS
    SELECT empno, job, sal
    FROM emp
    FOR UPDATE;
  ...
BEGIN
  OPEN c1;
  LOOP
    FETCH c1 INTO ...
    ...
    UPDATE emp
    SET sal = new_sal
    WHERE CURRENT OF c1;
  END LOOP;

6.8.8.2. Menggunakan LOCK TABLE

Kita menggunakan perintah LOCK TABLE untuk mengunci seluruh database tables dalam mode penguncian tertentu sehingga kita dapat membagi atau meniadakan akses kepada mereka. Sebagai contoh, perintah berikut mengunci table emp dalam mode row share. Penguncian-penguncian row share mengijinkan akses secara bersamaan ke table; penguncian-penguncian ini mencegah pengguna-pengguna lain mengunci seluruh table untuk penggunaan eksklusif. Penguncian table dibebaskan ketika transaksi kita memunculkan commit atau rollback.

LOCK TABLE emp IN ROW SHARE MODE NOWAIT;

Mode penguncian menentukan penguncian lain apa yang dapat ditempatkan pada table tersebut. Sebagai contoh, banyak pengguna dapat meminta penguncian-penguncian row share pada table pada waktu yang sama, namun hanya satu pengguna pada satu waktu yang dapat meminta penguncian eksklusif. Disaat satu pengguna memiliki penguncian eksklusif pada table, tidak ada pengguna lain yang dapat menambahkan, menghapus, atau mengubah baris-baris data pada table tersebut.

Penguncian table tidak pernah tetap memegang pengguna-pengguna lain dari melakukan query terhadap table, dan query tidak pernah meminta penguncian table. Hanya jika dua transaksi berbeda berusaha mengubah baris data yang sama, satu transaksi menunggu transaksi lain selesai.

6.8.8.3. Melakukan Fetch Melewati Commits

Klausa FOR UPDATE meminta penguncian-penguncian eksklusif terhadap baris data. Seluruh baris-baris data dikunci ketika kita membuka cursor, dan mereka dibuka pengunciannya, ketika kita melakukan commit terhadap transaksi. Jadi, kita tidak dapat melakukan fetch dari cursor FOR UPDATE setelah commit. Jika kita melakukannya, PL/SQL memunculkan exception. Dalam contoh berikut ini, cursor FOR loop gagal setelah penambahan data kesepuluh:

DECLARE
  CURSOR c1 IS
    SELECT ename
    FROM emp
    FOR UPDATE OF sal;
  ctr NUMBER := 0;
BEGIN
    FOR emp_rec IN c1 LOOP -- FETCH secara implisit
    ...
    ctr := ctr + 1;
    INSERT INTO temp VALUES (ctr, 'still going');
    IF ctr>= 10 THEN
      COMMIT; -- membebaskan penguncian-penguncian
    END IF;
  END LOOP;
END;

Jika kita ingin melakukan fetch melewati commit-commit, jangan menggunakan klausa FOR UPDATE atau CURRENT OF. Namun, gunakan pseudocolumn ROWID untuk menirukan klausa CURRENT OF. Secara sederhana kita menampilkan rowid dari setiap baris data ke dalam variable UROWID. Lalu, gunakan rowid tersebut untuk mengidentifikasi baris data terkini selama pengubahan-pengubahan dan penghapusan-penghapusan berikutnya. Contohnya sebagai berikut:

DECLARE
  CURSOR c1 IS
    SELECT ename, job, rowid
    FROM emp;
  my_ename emp.ename%TYPE;
  my_job emp.job%TYPE;
  my_rowid UROWID;
BEGIN
  OPEN c1;
  LOOP
    FETCH c1 INTO my_ename, my_job, my_rowid;
    EXIT WHEN c1%NOTFOUND;
    UPDATE emp
    SET sal = sal * 1.05
    WHERE rowid = my_rowid;
    -- ini menyerupai WHERE CURRENT OF c1
    COMMIT;
  END LOOP;
  CLOSE c1;
END;

Kita perlu berhati-hati. Dalam contoh terakhir, baris-baris data yang dihasilkan tidak terkunci karena tidak terdapat klausa FOR UPDATE yang digunakan. Jadi, pengguna-pengguna lain dapat tanpa sengaja menimpa pengubahan-pengubahan yang kita lakukan.

Cursor juga harus memiliki view read-consistent dari data, sehingga rollback segments yang digunakan dalam penghapusan tidak dibebaskan sampai cursor ditutup. Hal ini dapat memperlambat pemrosesan ketika banyak baris-baris data yang diubah.

Contoh selanjutnya menunjukkan bahwa kita dapat menggunakan atribut %ROWTYPE dengan cursor-cursor yang mereferensi pseudocolumn ROWID:

DECLARE
  CURSOR c1 IS
    SELECT ename, sal, rowid
    FROM emp;
  emp_rec c1%ROWTYPE;
BEGIN
  OPEN c1;
  LOOP
    FETCH c1 INTO emp_rec;
    EXIT WHEN c1%NOTFOUND;
    ...
    IF ... THEN
       DELETE FROM emp
       WHERE rowid = emp_rec.rowid;
    END IF;
  END LOOP;
  CLOSE c1;
END;

 

Pages: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

 

Buku ini membahas berbagai macam tip dan trik yang sangat berguna bagi Anda pembaca pengguna database Oracle. Pemula, mahasiswa, programmer, maupun database administrator yang mengharapkan solusi cepat dalam menangani permasalahan-permasalahan dalam penggunaan database Oracle dapat membaca buku ini. Anda tidak harus membaca buku ini secara urut karena buku ini di susun berdasarkan topik permasalahan, dan Anda dapat membaca topik-topik yang sesuai dengan permasalahan yang Anda hadapi.
Dapat di beli di toko buku Gramedia, Gunung Agung, Uranus, Karisma dsb. Harga Rp. 24.800,- (157 halaman)

 

Related Articles

 

Comments

[…] Interaksi PL/SQL dengan Oracle - 6,172 viewsFungsi Baris Tunggal - 4,245 viewsData Modelling dan Database Design - 3,954 viewsMengubah Table dan Constraint - 3,213 viewsTipe-tipe Data PL/SQL - 3,145 viewsPL/SQL Subprograms - 2,742 viewsMengontrol Akses User - 2,717 viewsCollections dan Records PL/SQL - 2,654 viewsMenampilkan Data - 2,572 viewsPendahuluan - 2,555 views […]

Leave a comment

(required)

(required)


*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word