предисловие
Поддержка InnoDB多粒度锁(multiple granularity locking)
, который позволяет行级锁
и表级锁
сосуществовать, иблокировка намеренийодин из них表锁
.
Замки намерения
Следует подчеркнуть, что блокировка намерения является своего рода不与行级锁冲突表级锁
, этот момент очень важен. Существует два типа блокировки намерений:
-
Общая блокировка намерения(преднамеренная общая блокировка, IS): транзакция намеренно добавляет несколько строк в таблицуобщий замок(S-замок)
-- 事务要获取某些行的 S 锁,必须先获得表的 IS 锁。 SELECT column FROM table ... LOCK IN SHARE MODE;
-
эксклюзивная блокировка намерения(намеренная монопольная блокировка, IX): транзакция намеренно добавляет определенные строки в таблицу.эксклюзивный замок(Х замок)
-- 事务要获取某些行的 X 锁,必须先获得表的 IX 锁。 SELECT column FROM table ... FOR UPDATE;
который:意向锁是有数据引擎自己维护的,用户无法手动操作意向锁
, перед добавлением общей/эксклюзивной блокировки к строке данных InooDB сначала получит соответствующую блокировку намерения таблицы данных, в которой находится строка данных.
Проблемы, решаемые блокировками намерения
Давайте сначала посмотрим на описание значения блокировки намерения в энциклопедии Baidu:
Если другая задача пытается применить разделяемую или монопольную блокировку на уровне таблицы, она блокируется блокировкой намерения на уровне таблицы, контролируемой первой задачей. Вместо проверки блокировок отдельных страниц или строк перед блокировкой таблицы второй задаче нужно только проверить блокировку намерения для таблицы.
представьте себе такуюusers
поверхность:MySql,InnoDB,Repeatable-Read:users(id PK, имя)
id | name |
---|---|
1 | ROADHOG |
2 | Reinhardt |
3 | Tracer |
4 | Genji |
5 | Hanzo |
6 | Mccree |
Транзакция A Получает эксклюзивный замок на ряд и не совершает:
SELECT * FROM users WHERE id = 6 FOR UPDATE;
Транзакция B хочет получитьusers
Блокировка стола для стола:
LOCK TABLES users READ;
Из-за разделяемых блокировок и эксклюзивных блокировок互斥
, поэтому транзакция B находится в паре представленийusers
При добавлении разделяемой блокировки к таблице необходимо убедиться, что:
- Ни одна другая транзакция в настоящее время не удерживает монопольную блокировку таблицы пользователей.
- Ни одна другая транзакция в настоящее время не удерживает монопольную блокировку какой-либо строки в таблице пользователей.
Чтобы определить, выполнено ли второе условие, транзакция B должна обеспечитьusers
Исходя из того, что для таблицы нет монопольной блокировки, проверьте, имеет ли каждая строка в таблице монопольную блокировку. Очевидно, что это очень неэффективная практика, но сблокировка намеренийПосле этого все по-другому:
Совместимый мьютекс блокировок намерений
Как блокировка намерения решает эту проблему? Во-первых, нам нужно знать мьютексы совместимости между блокировками намерений:
Общая блокировка намерений (IS) | Преднамеренная эксклюзивная блокировка (IX) | |
---|---|---|
Общая блокировка намерений (IS) | совместимый | совместимый |
Преднамеренная эксклюзивная блокировка (IX) | совместимый | совместимый |
которыйБлокировки намерений совместимы друг с другом, эммм... Тогда в чем смысл твоего существования?
Хотя блокировки намерений совместимы со своими собратьями, они будут совместимы с обычными блокировками.Эксклюзивный/общий замокВзаимоисключающий:
Общая блокировка намерений (IS) | Преднамеренная эксклюзивная блокировка (IX) | |
---|---|---|
Общий замок(и) | совместимый | взаимоисключающий |
Эксклюзивный замок (X) | взаимоисключающий | взаимоисключающий |
Примечание. Эксклюзивные/разделяемые блокировки здесь относятся к блокировкам таблицы! ! ! Блокировки намерения не являются взаимоисключающими с разделяемыми/исключительными блокировками на уровне строк! ! !
Теперь давайте вернемся к только чтоusers
Пример таблицы:
事务 A
Получил эксклюзивную блокировку строки без фиксации:
SELECT * FROM users WHERE id = 6 FOR UPDATE;
В настоящее времяusers
На столе два замка:users
на столеэксклюзивная блокировка намеренияс идентификатором 6 в строке данныхэксклюзивный замок.
Транзакция B хочет получить общую блокировку таблицы пользователей:
LOCK TABLES users READ;
В настоящее время事务 B
Обнаружить транзакцию Аusers
Таблицаэксклюзивная блокировка намерения, можно узнать, что事务 A
Неизбежно удерживайте некоторые строки таблицыэксклюзивный замок,Так事务 B
правильноusers
Запрос на блокировку таблицы будет исключен (заблокирован) без необходимости определять наличие монопольной блокировки для каждой строки данных в таблице.
Параллелизм блокировок намерений
Это включает в себя то, что я уже много раз подчеркивал:
Блокировки намерения не являются взаимоисключающими с разделяемыми/исключительными блокировками на уровне строк! ! !
Блокировки намерения не являются взаимоисключающими с разделяемыми/исключительными блокировками на уровне строк! ! !
Блокировки намерения не являются взаимоисключающими с разделяемыми/исключительными блокировками на уровне строк! ! !
Важные слова должны быть выделены жирным шрифтом три раза, поэтому блокировки по намерениям не повлияют на параллелизм нескольких транзакций при добавлении монопольных блокировок к разным строкам данных (в противном случае мы можем напрямую использовать обычные блокировки таблиц).
Наконец, давайте расширим пример таблицы пользователей выше, чтобы обобщить роль блокировок по намерению (может быть много разных блокировок в процессе блокировки части данных до освобождения, но здесь мы сосредоточимся только на блокировках по намерению):
id | name |
---|---|
1 | ROADHOG |
2 | Reinhardt |
3 | Tracer |
4 | Genji |
5 | Hanzo |
6 | Mccree |
事务 A
Получить ряд первымэксклюзивный замок, не представил:
SELECT * FROM users WHERE id = 6 FOR UPDATE;
-
事务 A
приобретенныйusers
на столеэксклюзивная блокировка намерения. -
事务 A
Получить данные в строке с идентификатором 6эксклюзивный замок.
после事务 B
хочу получитьusers
Таблицаобщий замок:
LOCK TABLES users READ;
-
事务 B
обнаружен事务 A
держатьusers
Таблицаэксклюзивная блокировка намерения. -
事务 B
правильноusers
Запрос на блокировку таблицы заблокирован (исключен).
Наконец事务 C
тоже хочу получитьusers
строка в таблицеэксклюзивный замок:
SELECT * FROM users WHERE id = 5 FOR UPDATE;
-
事务 C
Применятьusers
Таблицаэксклюзивная блокировка намерения. -
事务 C
обнаружен事务 A
держатьusers
Таблицаэксклюзивная блокировка намерения. - Поскольку блокировки намерения не являются взаимоисключающими, поэтому
事务 C
понятноusers
Таблицаэксклюзивная блокировка намерения. - потому что нет строки данных с идентификатором 5эксклюзивный замок, наконец-то
事务 C
Успешно получены данные на линии данныхэксклюзивный замок.
Суммировать
- Поддержка InnoDB
多粒度锁
, в некоторых сценариях блокировки на уровне строки могут сосуществовать с блокировками на уровне таблицы. - Блокировки намерения не исключают друг друга, но в дополнение к совместимости IS и S,
意向锁会与 共享锁 / 排他锁 互斥
. - IX и IS являются блокировками на уровне таблицы и не будут конфликтовать с блокировками X и S на уровне строк. Он будет конфликтовать только с X и S на уровне таблицы.
- Для обеспечения параллелизма реализованы блокировки намерений.
行锁和表锁共存
и满足事务隔离性
требования.
Использованная литература:
- InnoDB одновременно вставляет, фактически использует блокировку намерения?
- Что делает блокировка намерения InnoDB?