"едва ли не със SELECT ... FOR UPDATE ще постигне single row lock върху първия ред подходящ за резервация. "
При ENGINE=InnoDB
SELECT ... WHERE ... LIMIT 1 FOR UPDATE;
ще постави row lock върху първия намерен ред отговарящ на WHERE клаузата.
"1. Нека заявката изглежда така SELECT * FROM MyTable WHERE IsReserved = 0 FOR UPDATE
2. Нека в MyTable имаме няколко реда с IsReserved = 1
3. В зависимост от коректността на статистиките на db engine-а + ефективността на алгоритмите за lock escalation, съм готов да се обзаложа че в 95%+ от случаите заявката ще "осъмне" с tab lock. "
SELECT * FROM MyTable WHERE IsReserved = 0 FOR UPDATE;
ще осъмне с eXclusive row lock върху всички редове с
IsReserved = 0 в 100% от случаите дори и когато това са всички редове в таблицата.
SELECT * FROM MyTable WHERE IsReserved = 0 LIMIT 1 FOR UPDATE;
ще осъмне с X row lock върху един ред (първия намерен) в 100% от случаите.
Шансът при SELECT ... FOR UPDATE InnoDB да постави Tabel lock е нулев. Мога и да обясня защо ако трябва.
"4. Ако има индекс по IsReserved (нещо безумно като изпълнение, но "решение" което с голяма вероятност wiz би придложил гледайки предиката в WHERE клаузата на заявката) 100% от случаите ще имаме index lock на целия индекс."
Не знам какво точно имаш предвид под index lock в случая. InnoDB използва clustered index където държи Primary Key и точно това е което заключва. Няма вариант да заключи целия индекс обаче освен разбира се когато трябва да заключи всички елементи.
"5. В зависимост от нивото на изолация на транзакциите db engine-а може да се опита да предотврати "фантоми" и веднага ще сложи tab lock "
InnoDB предотвратява фантомите в почти всички случаи дори на ниво REPEATABLE READ, но това всъщност няма значение в случая.
"Питам се, след като на MyISAM му липсва A-то в ACID-а, може ли две сесии да UPDATE-нат един и същ ред едновременно и в резултат това: "
Не.
Въпросът кога точно на MyISAM му липсва A-то e с леко повишена трудност :) Не много, но да речем 6 по десетобална скала ;)
UPDATE x SET ......,
processed = UUID() ...
WHERE processed IS NULL LIMIT 1;
върши идеална работа при MyISAM точно защото при MyISAM няма транзакции и поради това гарантира невъзможност две сесии да променят един и същ ред.
MyISAM поддържа заключване само на ниво таблица.
Редактирано от salle на 18.12.08 03:20.