Spec-Zone .ru
спецификации, руководства, описания, API

14.2.3.6. Уход от Фантомной проблемы Используя Следующую ключевую Блокировку

Так называемая фантомная проблема происходит в пределах транзакции, когда тот же самый запрос производит различные наборы строк в разное время. Например, если a SELECT выполняется дважды, но возвращает строку во второй раз, которая не была возвращена в первый раз, строка является "фантомной" строкой.

Предположите, что есть индексирование на id столбец child таблица и что Вы хотите считать и заблокировать все строки от таблицы, имеющей значение идентификатора, больше чем 100 с намерением обновить некоторый столбец в выбранных строках позже:

SELECT * FROM child WHERE id > 100 FOR UPDATE;

Запрос сканирует индексировать запуск с первой записи где id больше чем 100. Позвольте таблице содержать наличие строк id значения 90 и 102. Если набор блокировок на индексировать записях в отсканированном диапазоне не запирает, вставляет сделанный в разрывы (в этом случае, разрыв между 90 и 102), другой сеанс может вставить новую строку в таблицу с id из 101. Если Вы должны были выполнить то же самое SELECT в пределах той же самой транзакции Вы видели бы новую строку с id из 101 ("фантом") в наборе результатов возвратился запросом. Если бы мы расцениваем ряд строк как элемент данных, новый фантомный дочерний элемент нарушил бы принцип изоляции транзакций, что транзакция должна быть в состоянии работать так, чтобы данные, которые это считало, не изменились во время транзакции.

Предотвратить фантомы, InnoDB использует алгоритм, названный следующим ключом, блокирующим, который комбинирует блокировку индексировать-строки с блокировкой разрыва. InnoDB выполняет привязку на уровне строки такого пути, которые, когда это ищет или сканирует таблицу, индексируют, это устанавливает коллективные или монопольные блокировки на индексировать записях, с которыми это встречается. Таким образом блокировки на уровне строки являются фактически блокировками индексировать-записи. Кроме того, следующая блокировка ключа на индексировать записи также влияет на "разрыв" прежде, чем это индексирует запись. Таким образом, следующая блокировка ключа является блокировкой индексировать-записи плюс разрыв, соединяют разрыв, предшествующий индексировать записи. Если у одного сеанса есть коллективная или монопольная блокировка на записи R в индексировании другой сеанс не может вставить новое, индексируют запись в разрыве сразу прежде R в индексировать порядке.

Когда InnoDB сканирует индексирование, оно может также заблокировать разрыв после последней записи в индексировании. Только это происходит в предыдущем примере: Чтобы предотвратить любого вставляют в таблицу где id было бы больше чем 100, блокировки, установленные InnoDB включайте блокировку на разрыве после id значение 102.

Можно использовать блокировку следующего ключа, чтобы реализовать уникальность, регистрируются в Вашем приложении: Если Вы читаете свои данные в режиме доли и не видите копию для строки, Вы собираетесь вставить, то можно безопасно вставить свою строку и знать, что набор следующей блокировки ключа на преемнике Вашей строки во время чтения предотвращает любого, тем временем вставляя копию для Вашей строки. Таким образом следующая ключевая блокировка позволяет Вам "заблокировать" небытие чего-то в Вашей таблице.

Блокировка разрыва может быть отключена как обсуждено в Разделе 14.2.3.5,"InnoDB Запись, Разрыв, и Следующие блокировки ключа". Это может вызвать фантомные проблемы, потому что другие сеансы могут вставить новые строки в разрывы, когда блокировка разрыва отключается.