Блокировки InnoDB являются эксклюзивными для INSERT / UPDATE / DELETE?

8

Я работаю вокруг ошибки MySQL "Обнаружен тупик при попытке получить блокировку; попробуйте перезапустить транзакцию" .

Я собираюсь обновить программу, чтобы разрешить взаимные блокировки. Возможно ли, что это SELECTутверждение приведет к ошибкам взаимоблокировки? Я знаю , что это только блокировка чтения , так что несколько выбирает не будет проблемой, но что , если есть INSERT, UPDATEили DELETEзаявление (с подзапросов можно с соединениями) и SELECTзаявление (возможно , с соединениями или подзапросов) ?

Возможно ли, что ошибка будет выдана SELECTвместо INSERT, UPDATEили DELETE.

История здесь, если вам интересно.

Брайан Филд
источник
+1, потому что это хороший вопрос, потому что он обнаруживает причуду InnoDB, о которой большинство людей не знают в сочетании с SELECT для таблиц InnoDB.
RolandoMySQLDBA

Ответы:

5

Прямой ответ на заголовок вашего вопроса - Нет.

Запросы 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 или более ранней версии, вы должны уничтожить все спящие соединения, чтобы снять блокировки.

RolandoMySQLDBA
источник
@Rolando - не правда ли с MVCC InnoDB, который читает никогда не блокировать (кроме случаев, когда вы используете, for updateконечно)?
Джек говорит, попробуй topanswers.xyz
@Jack - Если вы прочтете ссылки в первых трех пунктах, вы увидите, что MVCC не обсуждается. Это глубокий тупик в кластерном индексе, который даже MVCC не может смягчить.
RolandoMySQLDBA
@Rolando - я прочитал ссылки немного более внимательно и до сих пор не вижу никаких признаков того, что нормаль selectможет блокировать строки или каким-либо образом блокироваться DML в другой транзакции. Это, безусловно, верно для Oracle, и, насколько я могу судить, это верно и для InnoDB? Исключая случай, когда selectоператор фактически выполняет DML через функцию или какой-то другой обходной путь.
Джек говорит, попробуй topanswers.xyz
@Jack - Если SELECTs может заблокировать индекс, тем более, что ОБНОВЛЕНИЕ, как показано моими первыми 3 ссылками.
RolandoMySQLDBA