Andaikan saya mempunyai berbilang pekerja yang boleh membaca dan menulis ke jadual MySQL pada masa yang sama (contohnya jobs
). Tugas setiap pekerja ialah:
已排队
tertua RUNNING
Sila ambil perhatian bahawa apabila pekerja menjalankan langkah #1, mungkin tidak ada sebarang pekerjaan yang layak (iaitu QUEUED
).
Saya mempunyai pseudokod berikut setakat ini. Saya percaya jika langkah #1 tidak mengembalikan kerja, saya perlu membatalkan (ROLLBACK
) transaksi. Bagaimanakah saya melakukan ini dalam kod di bawah?
BEGIN TRANSACTION; # Update the status of jobs fetched by this query: SELECT id from jobs WHERE status = "QUEUED" ORDER BY created_at ASC LIMIT 1; # Do the actual update, otherwise abort (i.e. ROLLBACK?) UPDATE jobs SET status="RUNNING" # HERE: Not sure how to make this conditional on the previous ID # WHERE id = <ID from the previous SELECT> COMMIT;
Masih belum jelas apa yang anda mahukan. Tetapi katakan tugas anda ialah: cari
QUEUED
作业。将其状态设置为RUNNING
seterusnya dan pilih ID yang sepadan.Dalam persekitaran satu benang, anda hanya boleh menggunakan kod anda. Ekstrak ID yang dipilih ke dalam pembolehubah dalam kod aplikasi dan hantarkannya kepada pertanyaan KEMASKINI dalam klausa WHERE. Anda tidak memerlukan transaksi kerana hanya terdapat satu kenyataan tulis. Anda boleh meniru ini dalam SQLscript.
Andaikan ini status semasa anda:
Anda ingin memulakan kerja beratur seterusnya (id=2).
Anda akan dapat
Mulakan dari pilihan terakhir. Jadual akan mempunyai status berikut:
Lihat di DB Fiddle
Jika anda mempunyai pelbagai proses melancarkan kerja, anda perlu menggunakan
FOR UPDATE
锁定该行。但可以使用LAST_INSERT_ID()
untuk mengelakkan perkara ini:Bermula dari keadaan di atas, job 2 sudah berjalan:
Anda akan mendapat:
Status baharu ialah:
Lihat di DB Fiddle
Jika kenyataan KEMASKINI tidak menjejaskan mana-mana baris (tiada baris beratur),
ROW_COUNT()
将为0
.Mungkin terdapat beberapa risiko yang saya tidak sedar - tetapi itu juga bukan cara saya menghadapinya. Saya lebih suka menyimpan maklumat lanjut dalam jadual
jobs
. Contoh mudah:dan
Kini kerja yang sedang dijalankan tergolong dalam proses tertentu, anda boleh memilihnya hanya menggunakan
Anda mungkin ingin mengetahui lebih lanjut - cth.
queued_at
、started_at
、finished_at
.Minggu ini saya melaksanakan sesuatu yang hampir serupa dengan kes anda. Berbilang pekerja, masing-masing meraih "baris seterusnya" dalam satu set baris untuk diusahakan.
Kod pseudo adalah seperti ini:
Menggunakan
FOR UPDATE
adalah penting untuk mengelakkan keadaan perlumbaan (iaitu berbilang pekerja cuba mengambil baris yang sama).Lihat https://dev.mysql.com/ doc/refman/8.0/en/select-into.html untuk maklumat tentang
SELECT ... INTO
.