Недостатки блокировки строк в MySQL

Я использую блокировку строк (транзакции) в MySQL для создания очереди заданий. Используемый движок - InnoDB.

SQL-запрос

START TRANSACTION;
SELECT * 
FROM mytable 
WHERE status IS NULL 
ORDER BY timestamp DESC LIMIT 1 
FOR UPDATE;
UPDATE mytable SET status = 1;
COMMIT;

Согласно этому веб-страница,

The problem with SELECT FOR UPDATE is that it usually creates a single synchronization point for all of the worker processes, and you see a lot of processes waiting for the locks to be released with COMMIT.

Вопрос. Означает ли это, что при выполнении первого запроса, который занимает некоторое время для завершения транзакции, когда второй аналогичный запрос возникает до того, как первая транзакция будет зафиксирована, ему придется ждать его закончить до выполнения запроса? Если это правда, то я не понимаю, почему блокировка одной строки (что я предполагаю) повлияет на следующий запрос транзакции, который не потребует чтения этой заблокированной строки?

Кроме того, можно ли решить эту проблему (и по-прежнему добиться эффекта блокировки строк для очереди заданий), выполнив UPDATE вместо транзакции?

UPDATE mytable SET status = 1
WHERE status IS NULL
ORDER BY timestamp DESC
LIMIT 1

person Nyxynyx    schedule 26.09.2012    source источник
comment
Блокировка основана на механизме хранения — что вы используете?   -  person Adrian Cornish    schedule 26.09.2012
comment
Спасибо (и еще 9 символов впереди)   -  person Adrian Cornish    schedule 26.09.2012
comment
К сожалению, ваш status IS NULL ORDER BY запрос гарантирует, что полное сканирование таблицы mytable. индексов не поможет при поиске IS NULL. Если бы вы могли реорганизовать свой код, чтобы исключить значения состояния NULL, найти какое-то другое значение и использовать для этого индекс, вы бы сэкономили много времени на сканировании таблицы.   -  person O. Jones    schedule 26.09.2012
comment
Будет ли лучше установить значение по умолчанию для status на 0 и индексировать его?   -  person Nyxynyx    schedule 26.09.2012
comment
Да, эта схема значительно ускорит вашу операцию "найти следующую строку mytable, подходящую для обработки".   -  person O. Jones    schedule 26.09.2012


Ответы (1)


Если вы используете FOR UPDATE с механизмом хранения, использующим блокировки страниц или строк, строки, проверяемые запросом, блокируются для записи до конца текущей транзакции. Использование LOCK IN SHARE MODE устанавливает общую блокировку, которая позволяет другим транзакциям читать проверенные строки, но не update or delete их. и об этом запросе

UPDATE mytable SET status = 1
WHERE status IS NULL
ORDER BY timestamp DESC
LIMIT 1

так как innodb

автоматически получать блокировки во время обработки операторов SQL, я думаю, что это работает так же.

person Arun Killu    schedule 27.09.2012