Pertama, mengunci tabel tidak akan mencegah sesi lain mengeluarkan SELECT
pernyataan terhadap data.
Di Sesi 1, jika saya mengunci meja
SQL> lock table foo in exclusive mode;
Table(s) Locked.
Saya kemudian dapat memulai Sesi 2 dan menanyakan data semau saya
SQL> select * from foo;
COL1
----------
1
1
Di Oracle, penulis tidak memblokir pembaca sehingga Anda tidak akan pernah bisa mencegah sesi lain untuk menanyakan data dalam tabel.
Sepertinya apa yang Anda coba terapkan adalah penguncian pesimistis. Dalam hal ini, daripada mengunci tabel, Anda melakukan SELECT FOR UPDATE
yang mengunci entri tertentu yang ingin Anda proses. Selama semua sesi lain juga mencoba melakukan SELECT FOR UPDATE
(tergantung pada versi Oracle, berpotensi menambahkan SKIP LOCKED
kualifikasi dan/atau WAIT
kualifikasi). Itu mengunci baris tertentu yang sedang Anda proses dan memungkinkan sesi kedua memilih baris atau batas waktu yang berbeda atau menemukan tidak ada baris untuk diproses tergantung pada spesifikasi implementasinya. Itu tidak termasuk mengunci meja.
Satu-satunya cara agar kunci dilepaskan adalah agar sesi yang memperolehnya melepaskannya (umumnya dengan mengakhiri transaksi) atau agar sesi yang memperolehnya dihentikan. Jika aplikasi klien masih berjalan tetapi tidak melakukan apa pun untuk melepaskan kunci atau menghentikan sesi, kunci akan ditahan tanpa batas waktu. DBA perlu secara eksplisit mematikan sesi, membiarkan transaksi berputar kembali dan melepaskan kunci untuk membuat sistem bergerak kembali. Jika aplikasi klien berhenti berjalan atau, setidaknya, berhenti merespons (saya masih tidak tahu persis skenario kegagalan apa yang Anda diskusikan), ada kemungkinan bahwa mengaktifkan deteksi koneksi mati (DCD) melalui Parameter 'SQLNET.EXPIRE_TIME' di tingkat basis data akan menyebabkan basis data menentukan bahwa klien tidak responsif dan secara otomatis mematikan sesi, memutar kembali transaksi, dan melepaskan kunci.
Namun, jika ada beberapa sesi yang memproses data, umumnya lebih baik menggunakan beberapa bentuk penguncian optimis. Jika tidak, Anda sedang merancang sistem yang pasti akan membutuhkan DBA untuk segera menemukan dan mematikan sesi agar pengguna bisnis dapat bekerja kembali dan itu akan membutuhkan lebih banyak intervensi jika semakin sibuk. Itu bukan sesuatu yang disukai DBA dan bukan sesuatu yang dikeluhkan oleh pengguna bisnis. Skema penguncian optimis sederhana akan menjadi seperti
- Pilih kunci untuk diproses dan semacam tanggal yang menunjukkan kapan terakhir kali baris diperbarui.
- Perbarui kolom status ke "memproses" sehingga sesi lain tidak mencoba memproses baris yang sama.
- Proses entri di aplikasi Anda
- Setelah selesai memproses, perbarui data menggunakan kunci dan waktu yang Anda pilih di langkah pertama. Jika Anda memperbarui 1 baris, Anda tahu tidak ada sesi lain yang telah mengubah data yang dimaksud sejak Anda memilihnya. Jika Anda memperbarui 0 baris, Anda tahu bahwa beberapa sesi lain telah mengubah data sejak Anda memilihnya.
Dengan arsitektur semacam ini, relatif mudah untuk meminta database untuk melihat baris apa yang sedang diproses dan, misalnya, memiliki pekerjaan yang mengatur kolom status kembali ke "belum diproses" setelah beberapa waktu jika klien belum selesai. Sangat mudah bagi sesi lain untuk memilih baris yang berbeda untuk diproses. Dan relatif aman jika, misalnya, aplikasi membeku selama beberapa jam dan kemudian pulih karena hanya menemukan setelah selesai memproses bahwa beberapa sesi lain telah memproses ulang baris tersebut.