Типы и концепции блокировок в серии замков MySQL

MySQL

В mysql типы блокировки innodb можно разделить на четыре типа, включая блокировки строк и блокировки таблиц, которые

  • Основные замки — [Общие замки (Общие замки: S-замки) и Эксклюзивные замки (Эксклюзивные замки: X-замки)]
  • Блокировка намерения - [блокировка намерения, разделенная на общую блокировку намерения (блокировка IS) и монопольную блокировку намерения (блокировка IX)]
  • Блокировки строк — [блокировки записи, блокировки пробелов, блокировки следующего ключа, блокировки намерения вставки]
  • Блокировки с автоинкрементом - [ auto-inc locks ]

Ниже приведена соответствующая совместимость между различными блокировками (ps: я видел это в определенном блоге, я забыл, какой это был, и я отрезал его, когда подумал, что это хорошо):

Три алгоритма блокировки строк InnoDB:

  • Блокировка записи: блокировка записи одной строки, блокируется только сама запись.
  • Блокировка промежутка: блокировка промежутка, блокирует диапазон, но не включает саму запись. Цель состоит в том, чтобы предотвратить два текущих чтения одного и того же объекта и возникновение фантомных чтений.
  • Next-Key Lock: 1+2, блокирует диапазон и блокирует саму запись. Цель: решить фантомные показания

общий замок

Общие блокировки (S-блокировки), также известные как блокировки чтения, позволяют другим вещам добавлять S-блокировки, но не позволяют другим вещам добавлять X-блокировки.

Метод блокировки:

select...lock in share mode

Уведомление:

  • Для транзакций, использующих общие блокировки, другие транзакции могут только читать, но не записывать
  • Если операция обновления выполняется, она будет ждать, пока текущая транзакция не будет зафиксирована или откатана.
  • Если текущая транзакция также выполняет оператор SQL, которого ожидают другие транзакции, текущая транзакция будет выполнена успешно, а другие транзакции сообщат о взаимоблокировке.
  • и позволить другим замкам сосуществовать

эксклюзивный замок

Эксклюзивные блокировки Эксклюзивные блокировки (X-блокировки), также известные как блокировки записи, не позволяют другим транзакциям добавлять S- или X-блокировки.

метод блокировки:

select ... for update

→ для обновления: InnoDB по умолчанию является блокировкой на уровне строки.Когда есть явно указанный первичный ключ, используется блокировка строки, в противном случае используется блокировка таблицы. Детали использования следующие:

  • Явно укажите первичный ключ и, таким образом, запишите блокировки на уровне строк. пример:

    select name,age from tb_user where id = '1' for update(id是主键)
  • Явно укажите первичный ключ/индекс. Если нет записи, нет блокировки. пример:

    select name,age from tb_user where id = '1' for update(id是主键,但不存在id = 1的数据)
  • Нет первичного ключа/индекса, блокировка на уровне таблицы. пример:

    select name,age from tb_user where age = 12 for update(age是普通字段)
  • Первичный ключ/индекс неоднозначен, блокировка на уровне таблицы. пример:

    select name,age from tb_user where age = 12,id = '1' for update(id是主键,age不是,但数据库有此数据)

Уведомление:

  • Для транзакции монопольной блокировки другие вещи доступны для чтения, но операции обновления невозможны.
  • for update используется только с InnoDB, и транзакция должна быть открыта, чтобы вступить в силу между началом и фиксацией
  • Когда одна транзакция выполняется для обновления, другая транзакция будет ждать обновления до тех пор, пока предыдущая транзакция не зафиксирует или не откатится, или не отключится, чтобы снять блокировку, прежде чем получить блокировку для последующих операций (монопольные блокировки не могут сосуществовать).
  • innoDB.По умолчанию эксклюзивные блокировки добавляются для обновления, удаления и вставки, а операторы select по умолчанию не заблокированы.

оптимистическая блокировка

Прочитайте запись и вместе прочитайте эту версию, выполните операцию обновления и +1 к номеру версии записи. В это время номер версии отправляемой записи сравнивается с версией записи соответствующей таблицы в базе данных.Если он больше исходного номера версии базы данных, обновите его, в противном случае он считается просроченные данные и обновление не выполняется.. Цель состоит в том, чтобы решить проблему параллелизма.

Пример: два человека A и B одновременно изменяют одну и ту же запись. Предположим, что исходная сумма в базе данных составляет 100 юаней, сумма в A равна +100, а B переходит в базу данных -50.Нормальный результат равен 150, но из-за параллелизма результат может быть 200 или 50

Решение: A и B одновременно считывают версию данных как 1, количество пар A +100, изменяют версию данных на 2 и отправляют данные.В настоящее время версия данных равна 1, и обновление прошло успешно. B считывает версию данных 1, устанавливает количество -50, результат равен 50, изменяет версию данных на 2, отправляет данные и сравнивает исходную версию 2 базы данных, она не выше исходной версии, и обновление не удается

гэп замок

Блокировка промежутка — это блокировка промежутка между записями индекса или блокировка промежутка до или после последней записи индекса.

Предложение, которое использует уникальный индекс для поиска уникальной строки, не требует блокировки пробела (за исключением случая, когда условие поиска содержит несколько столбцов уникального индекса с несколькими столбцами, а индекс пробела возникает для нескольких запрошенных записей). Подробный пример выглядит следующим образом:

  • Предпосылка: (id — это индекс первичного ключа). Поскольку результат поиска является уникальной записью, блокировки пробелов использоваться не будут.

    select id,name,age from tb_user where id = '1'
  • Предпосылка: (id – индекс первичного ключа, age – неиндексное поле). Поскольку результат поиска может содержать более одной записи, для выбора идентификатора, имени и возраста из tb_user будет использоваться блокировка пробела, где id = '1'. и возраст = 13
Демо:
→ Структура данных:

CREATE TABLE `tb_user` (
  `id` int(10) NOT NULL,
  `name` varchar(255) NOT NULL DEFAULT '',
  KEY `index_id` (`id`),
  KEY `index_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

→ Инициализировать данные:


ps: сейчас я использую уровень изоляции базы данных по умолчанию: повторяемое чтение и локальное открытие двух клиентов для тестирования.

→ Клиент 1: откройте транзакцию и измените данные между идентификаторами 1-6 в клиенте.В настоящее время запись с идентификатором = 2 не существует.


→ Клиент 2: Откройте транзакцию и добавьте в базу данных запись с идентификатором 2, и вы обнаружите, что операция будет заблокирована!


--> Приведенная выше ситуация показывает наличие гэп-блокировки

--> Затем я изменил уровень изоляции на read commit, и вы можете обнаружить, что описанная выше операция добавления, то есть запись с id = 2, будет успешно добавлена, что указывает на то, что уровень изоляции read commit не будет использовать пробел замки.

Уведомление:

  • Единственная функция блокировки промежутка в InnoDB состоит в том, чтобы предотвратить операцию вставки других транзакций, чтобы предотвратить появление фантомных чтений, поэтому блокировка промежутка не различает разделяемые блокировки и монопольные блокировки.
  • Если InnoDB сканирует первичный ключ/уникальный индекс, то InnoDB будет использовать для блокировки только метод блокировки строки (блокировка записи) и не будет использовать метод блокировки пробела (блокировка следующего ключа).
  • Блокировка зазора просто предотвращает вставку других вещей в зазор, но не предотвращает блокировку зазора разными вещами в одном и том же зазоре.
  • Установка уровня изоляции на read_commited или включение системной переменной innodb_locks_unsafe_for_binlog (теперь устаревшей) явно запрещает использование блокировок с промежутками.

MVCC (чтение моментального снимка по сравнению с текущим чтением)

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

  • Чтение моментального снимка: чтение видимой версии записи без блокировки.
  • Текущее чтение: прочитайте последнюю версию записи, и запись, возвращенная текущим чтением, будет заблокирована, чтобы гарантировать, что другие вещи не изменят запись.

Итак, какие операции являются текущими операциями чтения, а какие — операциями чтения моментальных снимков?

→ Чтение моментального снимка: простая операция чтения относится к чтению моментального снимка без блокировки. (хотя у некоторых будут небольшие исключения)

Пример: выберите * из tb_user, где?

→ Текущее чтение: специальная операция чтения относится к текущему чтению и должна быть заблокирована.

  • select * from table where ? lock in share mode;

  • select * from table where ? for update;

  • вставить в табличные значения (…);

  • update table set ? where ?;

  • delete from table where ?;

Все приведенные выше операторы относятся к текущей прочитанной и прочитанной последней версии записи. Более того, после чтения также необходимо убедиться, что другие параллельные транзакции не смогут модифицировать текущую запись и заблокировать прочитанную запись. Среди них, в дополнение к первому оператору, блокировка S (общая блокировка) добавляется к записи чтения, а блокировка X (монопольная блокировка) добавляется для других операций.

Вышеприведенное является кратким изложением моих исследований блокировок баз данных за последние несколько дней.Если есть какие-то неточности, пожалуйста, поправьте меня~

Наконец, я рекомендую блог, написанный большой коровой, который очень подробный:Он Dengcheng.com/?Afraid=771#_TOC…