Пожалуйста, не говорите только проиндексированные блокировки БД! ! !

задняя часть база данных MySQL

Путь Java-инженера с 21,5 тысячами звезд GitHub к тому, чтобы стать богом, почему бы вам не прийти и не узнать об этом!

Путь Java-инженера с 21,5 тысячами звезд GitHub к тому, чтобы стать богом, разве вы не хотите узнать об этом!

В базе данных MySQL для решения проблемы параллелизма вводится множество механизмов блокировки, во многих случаях блокировка базы данных добавляется автоматически в процессе работы базы данных.

Поэтому многие программисты часто игнорируют реальный принцип механизма блокировки базы данных. Например, я часто спрашиваю кандидатов на собеседованиях,Знаете ли вы, что такое блокировка MySQL Innodb?

Я слышал много ответов на этот вопрос, но мало кто может ответить на него в совершенстве. Потому что, если вы хотите хорошо ответить на этот вопрос, вам нужно иметь определенное представление об уровне изоляции и индексе базы данных.

Заблокируйте презентации, связанные с MySQL Innodb, официальные документы в MySQL (Dev.MySQL.com/doc/Furious/…) имеет определенное введение, и введение этой статьи также основано на этом официальном документе.

Record Lock

** Блокировка записи, переведенная как блокировка записи, представляет собой блокировку, добавленную к индексной записи. **Например,SELECT c1 FROM t WHERE c1 = 10 For UPDATE;Запись c1=10 будет заблокирована, чтобы предотвратить вставку, обновление или удаление любой другой транзакцией строки со значением c1, равным 10.

Важно отметить, чтоБлокировка записи блокирует запись индекса.即使表没有定义索引,InnoDB也会创建一个隐藏的聚集索引,并使用这个索引来锁定记录。

Gap Lock

Gap Lock, переводится как gap lock, он относится к блокировке промежутка между записями индексаили блокировка пробела перед первой записью индекса или после последней записи индекса.

Итак, как тут понимать так называемый Gap (разрыв)?

Промежуток относится к месту в структуре данных индекса InnoDB, куда могут быть вставлены новые значения.

Когда вы блокируете набор строк с помощью инструкции SELECT...FOR UPDATE. InnoDB может создавать блокировки, которые применяются к фактическим значениям в индексе и промежуткам между ними. Например, если для обновления выбраны все значения больше 10, блокировка пробела не позволит другой транзакции вставить новые значения больше 10.

Поскольку это блокировка, это может повлиять на параллелизм базы данных., поэтому блокировка пробела будет работать только на уровне изоляции Repeatable Reads.

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

  • Для уникальных индексов с уникальными критериями поиска InnoDB блокирует только найденные записи индекса, а не пробелы.

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

То есть при обработке таких операторов, как SELECT FOR UPDATE, LOCK IN SHARE MODE, UPDATE и DELETE, в дополнение к уникальному поиску уникального индекса будет получена блокировка пробела или блокировка следующего ключа, то есть диапазон его сканирования будет заблокирован.

Next-Key Lock

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

Предположим, индекс содержит значения 10, 11, 13 и 20. Возможные блокировки следующего ключа для этого индекса включают следующие диапазоны:

(-∞, 10]
(10, 11]
(11, 13]
(13, 20]
(20, ∞ ]

Для последнего промежутка ∞ на самом деле не является записью индекса, поэтому, по сути, эта блокировка следующего ключа блокирует только промежуток после максимального значения индекса.

Таким образом, диапазон блокировки Next-Key остается открытым и закрытым справа.

Как и Gap Lock, Next-Key Lock действует только на уровне изоляции RR InnoDB.

Повторяющиеся чтения могут решить фантомные чтения

Многие люди видели введение уровня транзакций базы данных в Интернете и думают, что Repeatable Reads в MySQL может решить проблему неповторяющихся чтений, но не может решить проблему фантомных чтений, ее может решить только Serializable. Но на самом деле эта идея неверна.

Поскольку MySQL отличается от стандартного RR, у стандартного Repeatable Reads есть проблемы с фантомным чтением.Но Repeatable Reads в InnoDB решает проблему фантомного чтения RR с помощью блокировки следующего ключа..

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

По этому вопросу было широкое обсуждение, вы можете обратиться к:GitHub.com/YH это K/примечание…, есть много великих богов, которые выразили здесь свои взгляды.

Принцип блокировки MySQL

Record Lock, Gap Lock и Next-Key Lock были введены ранее, но правила блокировки не были описаны. Что касается правил блокировки, я понял это после прочтения статьи Ding Qi "45 Lectures on MySQL Practice". Правила блокировки, которые он обобщил, включают два "принципа", две "оптимизации" и одну "ошибку":

Принцип 1: Базовой единицей блокировки является блокировка следующего ключа. Это интервал открытия вперед и закрытия назад. Принцип 2: Блокируются только объекты, доступ к которым осуществляется в процессе поиска. Оптимизация 1: эквивалентный запрос к индексу, когда уникальный индекс заблокирован, блокировка следующего ключа вырождается в блокировку строки. Оптимизация 2: для запроса равнозначности по индексу, при переходе вправо и последнем значении, не удовлетворяющем условию равнозначности, блокировка следующего ключа вырождается в блокировку пробела. Ошибка: запросы диапазона для уникальных индексов будут обращаться до первого значения, не удовлетворяющего условию.

Предположим, в таблице базы данных на данный момент есть следующие записи:

когда мы выполняемupdate t set d=d+1 where id = 7Когда в таблице t нет записи с id=7, то:

  • Согласно принципу 1, блокировка блокировки является блокировкой следующего ключа, а диапазон блокировки сеанса A - (5,10];
  • Согласно оптимизации 2, это эквивалентный запрос (id=7), а id=10 не удовлетворяет условию запроса, и блокировка следующего ключа вырождается в блокировку промежутка, поэтому окончательный заблокированный диапазон равен (5,10) .

когда мы выполняемselect * from t where id>=10 and id<11 for updateкогда:

  • В соответствии с принципом 1 единицей блокировки является блокировка следующего ключа, и блокировка следующего ключа будет добавлена ​​к (5,10), а поиск диапазона продолжится и остановится, когда будет найдена строка с id=15.
  • В соответствии с оптимизацией 1 эквивалентное условие для идентификатора первичного ключа вырождается в блокировку строки, и добавляется только блокировка строки для строки с идентификатором = 10.
  • В соответствии с принципом 2 все доступы должны быть заблокированы, поэтому необходимо добавить блокировку следующего ключа (10,15]. Поэтому, наконец, добавляются блокировка строки id=10 и блокировка следующего ключа (10,15).

когда мы выполняемselect * from t where id>10 and id<=15 for updateВ то время: * Согласно принципу 1, блокировка блокировки является блокировкой следующего ключа, добавит блокировку следующего ключа в (10, 15] и потому, что идентификатор является уникальным ключом, суждение с циклом ID = 15 этой строки Должна остановиться. * Однако InnoDB будет сканировать первое поведение первого неудовлетворенного состояния, которое является Id = 20. И поскольку это сканирование сканирования, поэтому идентификатор индекса (15, 20] этот блок следующего ключа также будет заблокирован Отказ

Предположим, в таблице базы данных на данный момент есть следующие записи:

когда мы выполняемselect id from t where c=5 lock in share modeкогда:

  • В соответствии с принципом 1 единицей блокировки является блокировка следующего ключа, поэтому блокировка следующего ключа будет добавлена ​​к (0,5). Следует отметить, что c является общим индексом, поэтому доступ только к записи c=5 не может остановить немедленно. , вам нужно пройти вправо и сдаться, когда будет найдено c = 10.
  • Согласно принципу 2 все доступы должны быть заблокированы, поэтому добавьте блокировку следующего ключа в (5,10].
  • В соответствии с оптимизацией 2: суждение о равном значении, переход вправо, последнее значение не удовлетворяет условию равного значения c=5, поэтому оно вырождается в блокировку пробела (5,10).
  • Согласно принципу 2, только доступные объекты будут заблокированы. Этот запрос использует индекс покрытия и не должен получать доступ к индексу первичного ключа, поэтому в индексе первичного ключа нет блокировки.

когда мы выполняемselect * from t where c>=10 and c<11 for updateкогда:

  • В соответствии с принципом 1 единицей блокировки является блокировка следующего ключа, и блокировка следующего ключа будет добавлена ​​к (5,10), а поиск диапазона продолжится и остановится, когда будет найдена строка с id=15.
  • Согласно принципу 2 все доступы заблокированы, поэтому необходимо добавить блокировку следующего ключа (10,15].
  • Поскольку индекс c не является уникальным индексом, правило оптимизации отсутствует, то есть он не будет преобразован в блокировку строки, поэтому блокировки, добавленные последним сеансом A, являются двумя блокировками следующего ключа.

Суммировать

Выше мы представили механизм блокировки в InnoDB. Есть три вида замков, а именно замок записи, замок зазора и блокировку следующего ключа.

Блокировка записи означает блокировку записи, которая блокирует индексные записи. Gap Lock — это блокировка пробела, которая относится к промежутку между записями индекса. Next-Key Lock — это комбинация Record Lock и Gap Lock, которая одновременно блокирует индексные записи и пробелы. Его диапазон открыт слева и закрыт справа.

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

При этом для повышения производительности и параллелизма тоже есть два пункта оптимизации:

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

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

Позже давайте представим, почему RR является уровнем по умолчанию InnoDB, но «не честно», многие большие фабрики будут изменять уровень базы данных по умолчанию на RC.

Об авторе:Hollis, человек с уникальным увлечением программированием, технический эксперт Alibaba, соавтор «Трех курсов для программистов» и автор серии статей «Дорога к Java-инженерам».

Обратите внимание на общедоступный номер【Hollis], фоновый ответ «Карта Бога» может получить расширенную карту разума инженеров Java.