Прямой ответ на заголовок вашего вопроса - Нет.
Запросы SELECT могут выполнять блокировки для gen_clust_index , также называемого кластерным индексом.
Вот три вопроса DBA Stack Exchanges, которые я агрессивно просматривал с помощью @RedBlueThing , человека, который задавал эти вопросы. @RedBlueThing нашел обходные пути для своих вопросов.
Просто чтобы держать ваш вопрос в перспективе, когда вы просматриваете эти ответы (не смотрите слишком глубоко, даже у меня кружится голова при взгляде на мои собственные запутанные ответы), должно быть быстро очевидно, что запросы SELECT могут блокировать данные.
У вас также есть особые случаи SELECT, где вы можете заблокировать определенные строки по требованию .
ОБНОВЛЕНИЕ 2011-08-08 16:49 EDT
Вы задали вопрос о вариации: «Возможны ли исключения SELECT из InnoDB при помощи SELECT?» Ответ на это может быть «Да» при определенных условиях. Что это за состояние? Если в результате ошибки откатывается только один оператор SQL, некоторые блокировки, установленные этим оператором, могут быть сохранены. Это происходит потому, что InnoDB хранит блокировки строк в таком формате, что впоследствии он не может знать, какая блокировка была установлена каким оператором .
Исходя из этого утверждения, последовательность событий, вызывающих это, теоретически может быть следующей:
- Ваш SQL ОБНОВЛЯЕТ одну строку, но генерирует ошибку
- ОБНОВЛЕНИЕ вызывает откат одной строки
- Ряд имеет затяжной замок
Лично это последнее утверждение пугает меня. Было бы неплохо, чтобы MySQL сообщал всем об этой причуде. Тем не менее, это утверждение взято из документации MySQL. (О да, Oracle владеет InnoDB)
ОБНОВЛЕНИЕ 2015-09-22 18:40 EST
Ранее в том же году я узнал, что у Percona есть классная проверка Nagios, чтобы найти эти надоедливые замки, скрывающиеся за спящими соединениями. Все, что вам нужно сделать, это запустить код по этой ссылке:
SELECT COALESCE(MAX(IF(p.command = 'Sleep', p.time, 0)), 0) AS idle_in_trx
FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS AS w
INNER JOIN INFORMATION_SCHEMA.INNODB_TRX AS b ON b.trx_id = w.blocking_trx_id
INNER JOIN INFORMATION_SCHEMA.INNODB_TRX AS r ON r.trx_id = w.requesting_trx_id
LEFT JOIN INFORMATION_SCHEMA.PROCESSLIST AS p ON p.id = b.trx_mysql_thread_id;
Это будет работать только для MySQL 5.5+. Если у вас MySQL 5.1 или более ранней версии, вы должны уничтожить все спящие соединения, чтобы снять блокировки.