Ini menyebabkan kebuntuan karena UPDATE
kueri mengunci semua baris dalam tabel, dan tergantung pada indeks yang digunakan (atau kekurangannya), dua sesi berbeda berpotensi menguncinya dalam urutan yang sedikit berbeda. Ingat bahwa UPDATE
, DELETE
, dan SELECT ... FOR UPDATE
akan mengunci semua baris yang mereka temui, apakah baris tersebut cocok dengan semua WHERE
kondisi atau tidak. Jadi saat menggunakannya, Anda harus berusaha keras untuk memastikan bahwa mereka menemukan baris sesedikit mungkin, dengan menggunakan indeks (idealnya kunci utama) dan menghindari kondisi yang tidak jelas atau pemilihan luas.
Saran saya untuk antrian kerja cukup universal:Kunci sesedikit mungkin sesering mungkin dan selalu dalam urutan deterministik. Jadi, umumnya:
- Gunakan pembacaan yang tidak mengunci (
SELECT
biasa) ) untuk menemukan pekerjaan yang harus dilakukan dengan mencari hal-hal yang diketahui pekerja Anda bagaimana melakukannya dan saat ini tidak diklaim (lease_owner IS NULL AND lease_expiry IS NULL
-- atau serupa). - Pilih satu item pekerjaan (atau beberapa jika Anda berani, tetapi yang satu jauh lebih sederhana dan biasanya memungkinkan kinerja yang dapat diterima dengan sempurna).
- Perbarui item pekerjaan Anda (untuk mengklaimnya, tetapi untuk kasus apa pun juga perlu diperbarui):
- Buka transaksi.
- Kunci item pekerjaan yang Anda pilih dengan
SELECT ... FOR UPDATE
-- Jika tidak diklaim lagi, batalkan dan pilih yang lain. - Perbarui item pekerjaan yang Anda pilih dengan id pekerja Anda dan waktu kedaluwarsa untuk sewa Anda.
- Segera lakukan transaksi Anda.
- Mulai kerjakan item pekerjaan sewaan Anda.
- Dalam beberapa proses lain, poller lain mencari pekerjaan yang ditinggalkan dan membatalkan klaimnya (melalui proses pembaruan yang sama di atas).
Anda dapat dengan mudah mendapatkan throughput yang sangat tinggi dengan desain ini (ribuan pekerjaan per detik), dan pada dasarnya tanpa perselisihan dan tanpa masalah pemesanan. Pengoptimalan untuk memilih pekerjaan yang cenderung tidak berkonflik dengan poller lain sederhana dan efektif (misalnya modulus pada ID Pekerjaan atau serupa, dipilih untuk menghindari kelaparan pekerjaan). Kuncinya adalah untuk mengingat bahwa konflik dalam pemilihan pekerjaan oke -- batalkan saja dan coba lagi dan semuanya berjalan dengan sangat cepat.
Semua penulisan penguncian untuk item/pekerjaan antrian pekerjaan harus dilakukan hanya pada baris tunggal dan dengan kunci utama hanya .