Kod paralelne obrade podataka koji se nalaze u MySQL tabeli kao mehanizam zaključavanja odavno koristim polje u koje upisujem ID od procesa koji obrađuje trenutno neki slog. Ali se kao problem postavi šta se desi ako neki od tih procesa umre, i određeni slog ostane zaključan od strane procesa koji je umro i nikad ga neće otkljčati.
Ranije sam za to koristio file lock i scriptu koja monitoriše da li je neki child umro i u tom slučaju jednostavno oslobađa sve što je taj proces imao zaključano. Ali, postoji mnogo jednostavnije i lakše rešenje bez file lockova i procesa za monitoring.
Primer tabele:
CREATE TABLE `dataobj` ( `id` INT(11) NOT NULL, `connection_id` INT(11) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; |
Process zaključavanja određenog broja slogova koje ćemo procesirati:
UPDATE dataobj SET connection_id = CONNECTION_ID() WHERE 1=1 AND (connection_id = 0 OR connection_id NOT IN (SELECT id FROM information_schema.processlist)) LIMIT 2; |
U where imamo kriterijum koji selektuje samo nezaključane slogove ( connection_id = 0 ), kao i one koji su zaključane od strane scripte koje su umrle (otkačile se sa baze). 1=1 je dodatni kriterijum ako želimo samo određene slogove da obrađujemo. A limit nam kontroliše kolko slogova želimo da preuzmemo za obradu.
Potom je potrebno da pokupimo one koje smo uspešno zaključali:
SELECT * FROM dataobj WHERE connection_id = CONNECTION_ID() |
Po zavšenom poslu za odključavanje možemo da uradimo jednostavno setovanje connection_id polja na nulu.