UPDATE
заключва реда, така че не е необходимо да го заключвате първо. Ако се опитате да UPDATE
припокриващи се набори от редове едновременно, вторият UPDATE
ще изчака транзакцията на първия да се ангажира или върне назад.
Големият проблем с вашия подход - освен факта, че UPDATE
няма LIMIT
клауза - е, че множество работници ще се опитат да хванат едни и същи редове. Ето какво се случва:
- worker1:Филтрира таблицата, за да намери 200 реда и ги заключва
- worker1:започва да актуализира редовете
- worker2:филтрира таблицата, за да намери 200 реда
- worker2:опитва да започне да актуализира редове, но е избрал същите редове като worker1, така че блокира при заключване на worker1
- worker1:Завършва актуализирането на редовете
- worker2:След освобождаване на заключването проверява отново условието WHERE и открива, че никой от редовете вече не съвпада, защото worker1 ги е актуализирал. Актуализира нула редове.
... и повторете!
Трябва да:
- Имате централна опашка раздаване на редове по подходящ начин, безопасен за едновременност; или
- Задайте на работниците неприпокриващи се диапазони от идентификатори, върху които да работят
Що се отнася до LIMIT
- можете да използвате WHERE id IN (SELECT t.id FROM thetable t LIMIT 200 ORDER BY id)
- но ще имате същия проблем и с двата работници, които избират един и същ набор от редове за актуализиране.