MVCC Неблокирующие чтения - это, в некотором смысле, отсутствие блокировки . MVCC позволяет одному или нескольким читателям получить доступ к данным с возможностью повторного чтения, даже когда писатели обновляют одинаковые строки. В этом случае блокировка не требуется.
Например, если я изменяю какую-либо строку, InnoDB немедленно создает копию старой версии этой строки. Ваша параллельная транзакция, считывающая эти данные, может продолжить чтение копии. Эта старая версия сохраняется в базе данных до тех пор, пока длится ваша транзакция.
Если вы начнете новую транзакцию, вы увидите самую последнюю зафиксированную версию строки, и старая версия может в конечном итоге быть подвергнута сборке мусора, что освобождает некоторое пространство.
Блокировка - это когда несколько писателей пытаются обновить одни и те же строки. Только один писатель может обновлять строку за раз, и первый, обновляющий строку, блокирует ее до тех пор, пока они не передадут изменение. Другие авторы должны ждать, пока первый писатель не совершит. Но, по крайней мере, с блокировкой на уровне строк, они имеют конфликт только в том случае, если обновляют ту же строку .
Хорошим ресурсом для получения дополнительной информации о параллелизме и блокировке InnoDB является Высокопроизводительный MySQL, 3-е изд.
Комментарий от @AlexYakunin:
Любое количество одновременных потоков может получить общую блокировку в одной строке. Но эксклюзивная блокировка требует, чтобы не было блокировок любого типа - только один поток за раз может получить эксклюзивную блокировку.
UPDATE всегда запрашивает монопольную блокировку, и это более распространенный случай. Общие блокировки используются в некоторых более экзотических случаях в InnoDB:
Я обновляю дочернюю строку с внешним ключом для родительской таблицы. Я получаю X-блокировку для дочерней строки и S-блокировку для родительской строки. По сути, никто не может обновить родительскую строку, пока я обновляю строку, которая зависит от этого родителя.
Я явно использую SELECT ... LOCK IN SHARE MODE
, чтобы заблокировать обновления некоторых строк во время чтения. Обычно в этом нет необходимости.
Я выполняю любые SELECT
, пока уровень изоляции моей транзакции равен SERIALIZABLE
(это не распространено).
Я выдаю INSERT, которая приводит к ошибке дубликата ключа, мой поток запрашивает общую блокировку строки.
См. http://dev.mysql.com/doc/refman/5.6/en/innodb-locks-set.html для более подробной информации и примеров.