Почему MySQL InnoDB также устанавливает блокировки Gap для операции обновления / удаления? - PullRequest
1 голос
/ 26 марта 2020

Насколько я знаю, блокировка пробела используется для предотвращения фантомного чтения, и я обнаружил, что блокировка пробела устанавливается блокировкой чтения в большинстве статей с помощью поиска Google.

Блокировка пробела - это блокировка на разрыв между индексными записями или блокировку на разрыв перед первой или после последней индексной записи. Например, ВЫБРАТЬ c1 ОТ t ГДЕ c1 МЕЖДУ 10 И 20 ДЛЯ ОБНОВЛЕНИЯ; запрещает другим транзакциям вставлять значение 15 в столбец t.c1, независимо от того, было ли уже такое значение в столбце, потому что промежутки между всеми существующими значениями в диапазоне заблокированы.

https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html#innodb -gap-locks

Я полагаю, это (установить блокировку пробела при блокировке читать) достаточно. Почему update , delete также устанавливает блокировку пробела.

UPDATE ... WHERE ... устанавливает эксклюзивную блокировку следующего ключа на каждой записи поиска. Однако для операторов, которые блокируют строки с использованием уникального индекса для поиска уникальной строки, требуется только блокировка записи индекса.

https://dev.mysql.com/doc/refman/8.0/en/innodb-locks-set.html

И Другая проблема заключается в том, что произошло, если нет подходящего индекса, к которому можно прикрепить блокировку пробела? Откатывается ли блокировка всей таблицы?

Здесь мы предположили, что по умолчанию используется уровень изоляции транзакции Repeatable Read.

1 Ответ

1 голос
/ 26 марта 2020

Это зависит от условий в вашем SELECT, UPDATE или DELETE. Они устанавливают блокировку промежутка, чтобы другие параллельные сеансы не добавляли в набор строки, которые соответствовали бы условиям.

В InnoDB операторы блокировки всегда блокируют самые последние зафиксированные версии строк. Таким образом, они на самом деле не подчиняются снимку REPEATABLE READ. Они действуют больше как READ-COMMITTED.

Поэтому, если вы сделаете оператор, подобный следующему:

UPDATE FROM MyTable SET ... WHERE created_at > '2020-03-22';

Он должен заблокировать пробел после наибольшего значения созданного_катода, что предотвратит другие сеансы от добавления новых строк.

Это имитировать REPEATABLE READ, чтобы убедиться, что если вы снова запустите тот же UPDATE, это повлияет на те же строки, и это не повлияет случайно новые строки.

...