Блокировка Mysql и практика

задняя часть MySQL

1. Классификация замков

Блокировки в innodb делятся на S-блокировки, то есть общие блокировки, и другие X-блокировки, эксклюзивные блокировки, такие как:

Общий замок(и)

select * from supplier where id=5 lock in share mode;

Эксклюзивный замок (X)

select * from supplier where id=5 for update;

Или операторы вставки, удаления, обновления, которые являются эксклюзивными блокировками.

совместимость

Совместимость этих двух замков следующая:

X S
X N N
S N Y

блокировка намерения

Можно понять, что он принадлежит родительскому узлу блокировки S и блокировки X, то есть, если вы хотите получить блокировку S или блокировку X, вы должны сначала получить блокировку намерения, то есть блокировку IS или IX. , совместимость этих двух типов замков следующая

X S IX IS
X N N N N
S N Y N Y
IX N N Y Y
IS N Y Y Y

Неявный замок

Я тоже пьян, зачем тебе столько концептов заниматься. . Этот тип блокировки можно считать не заблокированным, когда нет конфликта. Блокировка в это время является неявной блокировкой. При возникновении конфликта блокировка будет обновлена ​​до явной блокировки. Давайте проиллюстрируем это на примере:

Транзакция 1 (где возраст — нормальный показатель)

select * from test01 where age=21 for update;

Мы видим, что в mysql на самом деле нет блокировки:

Транзакция 2

insert into test01(id,name,age) values(8,'zzh',22);

В это время, поскольку [21,23) имеет блокировку пробела, будет заблокирована транзакция 2. В это время посмотрите на запись блокировки в mysql

Видно, что хотя транзакция 1 использовала... для обновления в начале, была добавлена ​​неявная блокировка, поскольку конфликта не было, при запуске транзакции 2 возник конфликт, поэтому блокировка транзакции 1 была изменена на реальную замок.

2. Анализ блокировки и практика

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

2.1 Вставьте замки намерения

Первый взглядОфициальный сайт объясняет блокировку

Сосредоточимся на красной области: при возникновении конфликта к местоположению индекса будет добавлена ​​блокировка S, а общая блокировка может легко привести к взаимоблокировке.На официальном сайте есть пример, специально объясняющий эту общую блокировку. Возникает взаимоблокировка, то есть три коллеги по транзакции выполняют оператор вставки, и одна из транзакций откатывается, что приводит к взаимоблокировке:

Мы можем просто снова смоделировать эту ситуацию:

Транзакция 1

 insert into test01(id,name,age)values(12,"zzh",33);

Транзакция 2

 insert into test01(id,name,age)values(12,"zzh",33);

Транзакция 3

 insert into test01(id,name,age)values(12,"zzh",33);

Действуйте, как показано ниже:

Посмотрим на записи блокировок в Mysql

Среди них это доказывает, что когда блокировка намерения конфликтует, запрашивается блокировка S, а затем мы откатываем транзакцию 1.

Транзакция 1

rollback

В это время мы видим, что транзакция 2 прошла успешно, а транзакция 3 зашла в тупик.

Мы можем видеть из журнала взаимоблокировки:

  • Транзакция 2: Ожидание блокировки намерения вставки с режимом блокировки X
  • Транзакция 3: ожидание блокировки намерения вставки с режимом блокировки X; владение блокировкой записи с режимом блокировки S
  • Подразумеваемое условие: транзакция 2 также имеет блокировку записи с режимом блокировки S, что приводит к взаимоблокировке.Журнал взаимоблокировок не будет распечатывать блокировки, уже принадлежащие транзакции, которая, наконец, успешно получила блокировку.

Таким образом, возникает транзакция 2-> транзакция 3, транзакция 3-> транзакция 2.

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

Давайте рассмотрим другую ситуацию:

Транзакция 1 (идентификатор транзакции = 2944)

select * from test01 where age=21 for update;

Транзакция 2 (идентификатор транзакции = 2945)

insert into test01(id,name,age)values(2,"zzh",22);

Транзакция 3 (идентификатор транзакции = 2946)

select * from test01 where age=21 lock in share mode;

Выполнить следующим образом

Заблокировать записи в mysql

Мы видим, что

  • Транзакция 1: (X, RECORD LOCK) в первичном ключе, (X, RECORD LOCK) в age_idx
  • Транзакция 2: в (S, RECORD LOCK) первичного ключа, как мы упоминали ранее, транзакция 2 имеет конфликт при получении блокировки намерения вставки, поэтому она заблокирована для получения (S, RECORD LOCK)
  • Транзакция 3: (S, RECORD LOCK) в age_idx,

Затем мы фиксируем транзакцию 1Транзакция 1

commit;

  • Транзакция 2: блокировка S была успешно добавлена, но произошел конфликт уникальных ключей, и об ошибке было сообщено напрямую.Существует очень важный момент, обнаруженный в наличии записи, сразу после получения успеха транзакции банк плюс S-блокировка, но, несмотря на то, что он был предоставлен, S-блокировки не снимаются.
  • Транзакция 3: Блокировка S получена успешно, но она находится на age_idx, что отличается от транзакции 2.

Давайте повторно выполним транзакцию 1

Транзакция 1 (идентификатор транзакции = 29467)

select * from test01 where age=21 for update;

Результат выполнения блокируется:

Давайте посмотрим на записи блокировки в mysql:
Видно, что транзакция 3 имеет блокировку S на age_idx, которая блокирует блокировку X для получения транзакцией 1. В это время мы отправляем транзакцию 3.Транзакция 3 commit;

Мы обнаружили, что транзакция 1 все еще заблокирована, посмотрите записи блокировки в mysql.

Теперь я понимаю,Хотя транзакция 2 не может быть выполнена, блокировка S, добавленная из-за конфликта блокировок намерения вставки, не снимается, поэтому транзакция 1 по-прежнему заблокирована.. Только когда мы фиксируем транзакцию 2, транзакция 1 действительно выполняется.

2.2 select...for update

Блокировка оператора делится на два случая

  • Запись существует: если в режиме RC добавить (X, RECORD LOCK), в режиме RR добавить (X, NEXT-KEY LOCK), блокировки несовместимы друг с другом
  • Запись не существует: добавить (X, GAP) LOCK, а блокировка совместима,Но он не совместим с блокировками Insert Intention Locks, что может легко привести к тупиковой ситуации.

2.2.1 Ожидание взаимоблокировки между разными индексами

Транзакция 1

select * from test01 where age=21 for update;

Транзакция 2

insert into test01(id,name,age)values(3,"zzh",22);

Транзакция 1

insert into test01(id,name,age)values(3,"zzh",100);

Выполните результаты в указанном выше порядке:

Мы обнаружили, что возникла взаимоблокировка, и транзакция 1 была успешно выполнена после того, как транзакция 2 была отменена mysql. Давайте посмотрим на конкретный журнал взаимоблокировок.

Через журнал взаимоблокировок мы можем его проанализировать

  • Транзакция 1: с age_idx (X, NEXT-KEY LOCK) возникает конфликт с блокировкой намерения вставки, поэтому дождитесь (S, RECORD LOCK) в позиции id=3.
  • Транзакция 2: ожидание блокировки намерения вставки age_idx (блокировка намерения вставки доступна не только для первичного ключа)
  • Неявные условия: хотя транзакция 2 ожидает блокировку намерения вставки в age_idx, блокировка намерения вставки в позиции id=3 выполнена успешно, поэтому возникает конфликт в транзакции 1, добавляющей блокировку намерения вставки в этой позиции.

2.2.2 Тупик, вызванный отсутствием записей

Транзакция 1 (идентификатор транзакции = 29684)

select * from test01 where age=21 for update;

Транзакция 2 (идентификатор транзакции = 29683)

select * from test01 where age=21 for update;

Транзакция 1

insert into test01(id,name,age)values(3,"zzh",22);

Результат выполнения следующий

можно увидеть

  • Транзакция 1 и транзакция 2 одновременно удерживают блокировку пробела для записи age = 22. Поскольку запись не существует, блокировка пробела в это время совместима.
  • Однако в записи нет совместимой блокировки промежутка, а блокировка намерения вставки несовместима, поэтому блокировка намерения вставки, запрошенная транзакцией 1 для индекса age=22, будет ожидать.

Транзакция 2

insert into test01(id,name,age)values(3,"zzh",22);

Из приведенного выше анализа также можно сделать вывод, что есть два случая ожидания транзакции 2:

(1) Как и транзакция 1, дождитесь блокировки намерения вставки для возраста = 22. В это время обнаружено, что транзакция 1 уже ожидает блокировку намерения вставки в этой позиции, затем дождитесь блокировки S в этой позиции.

(2) Хотя транзакция 1 ожидает блокировки намерения вставки с возрастом = 22, блокировка намерения вставки с id = 3 успешно добавлена, поэтому, если транзакция 2 ожидает блокировки намерения вставки с id = 3, также будет конфликта, то просто дождитесь блокировки S в этом месте

Следовательно, обе эти ситуации приведут к взаимоблокировке в транзакции.Рассмотрим лог взаимоблокировки подробно:

Мы видели:

  • Транзакция 1 ожидает блокировку намерения вставки в возрасте 22 лет.
  • Транзакция 2 ожидает блокировки S с идентификатором = 3, что является вторым проанализированным нами случаем, а транзакция 2 имеет блокировку пробела с возрастом = 22.

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

insert into test01(id,name,age)values(3,"zzh",22);

Мы узнали, что когда запись не существует, если для этой записи выполняется оператор select...for update, оператор добавит блокировку пробела в пустую позицию, что более опасно. первичный ключ, и в это время, если вы запросите несуществующую запись, она добавит блокировки пробелов ко всем пробелам, которые будут вставлены в будущем, что приведет к тому, что данные не будут вставлены в таблицу в будущем, что является чрезвычайно опасен.

3. Резюме

В этой статье мы представили блокировки в mysql и некоторые взаимоблокировки, с которыми можно столкнуться на практике, и проанализировали их с помощью нескольких демонстраций.Для анализа блокировок в статье hedecheng, упомянутой в статье, есть глубокое объяснение , поэтому эта статья не обобщает его. Суть в том, чтобы проанализировать весь процесс на нескольких практических примерах. Основное внимание уделяется блокировкам намерения вставки и некоторому анализу блокировок в select...for update. В следующей статье будет представлен механизм MVCC для mysql.