предисловие
В прошлой главе мы говорили о принципе блокировок на уровне строк. Здесь вы должны хорошо понимать слова. Давайте поговорим о моментах, на которые следует обратить внимание и которых следует избегать после изучения блокировок на уровне строк.
Когда мы используем блокировки, есть проблема, которую нужно замечать и избегать: мы знаем, что эксклюзивные блокировки имеют характеристики взаимного исключения. Когда транзакция или поток удерживают блокировку, это не позволяет другим потокам получить блокировку, что приведет кБлокирующее ожидание, если циклическое ожидание, может привести ктупик.
Нам нужно проанализировать эту проблему с нескольких аспектов, один — почему блокировка не снимается, второй — что делать, если она заблокирована, и третий — как возникает взаимоблокировка и как ее избежать. Посмотрим на текстовую часть.
Старые правила, садись в самолет первым:
- Связано с MySQL (1) - как выполняется оператор запроса
- Связано с MySQL (2) - как выполняется оператор обновления
- Связано с MySQL (дополнительная статья) - логическая структура хранения innodb;
- Связано с MySQL (3) - вывод модели данных индекса и подробное введение в B + Tree;
- Связано с MySQL (четыре) - индекс ключевых точек оптимизации производительности
- Связано с MySQL (5) — подробное введение в функции транзакций и уровни изоляции
- Связанный с MySQL (6) — реализация уровня изоляции транзакций (MVCC)
- Связано с MySQL (7) - введение и использование блокировки innodb
- Связано с MySQL (8) — углубленный анализ блокировок на уровне строки innodb
Упомянутая выше карта мозга выглядит следующим образом.
текст
тупик
Открытие замка и блокировка
Резюме: когда снимается блокировка?
Транзакция завершается (фиксация, откат); клиентское соединение разорвано.
Если транзакция не сняла блокировку, как долго другие транзакции будут заблокированы? Будет ли это ждать вечно? Если это так, в случае большого количества одновременных доступов, если большое количество транзакций приостановлено из-за того, что требуемые блокировки не могут быть получены немедленно, это займет много ресурсов компьютера, вызовет серьезные проблемы с производительностью и даже перетащит через базу данных. .
[Err] 1205 - Превышено время ожидания блокировки; попробуйте перезапустить транзакцию В MySQL есть параметр для управления временем ожидания получения блокировки, по умолчанию 50 секунд.
show VARIABLES like 'innodb_lock_wait_timeout';
В случае тупиковой ситуации, независимо от того, как долго вы ждете, вы не можете получить блокировку В этом случае вам нужно ждать 50 секунд? Это
Разве 50 секунд не были потрачены впустую?
Давайте сначала посмотрим, когда возникает взаимоблокировка.
Возникновение и обнаружение взаимоблокировки
Демонстрация тупика:
Session 1 | Session 2 |
---|---|
begin; select * from t2 where id =1 for update; |
|
- | begin; delete from t2 where id =4 ; |
update t2 set name= '4d' where id =4 ; | |
- | delete from t2 where id =1 ; |
В первой транзакции взаимоблокировка была обнаружена и немедленно вышла, а вторая транзакция получила блокировку, не дожидаясь 50 секунд:
[Err] 1213 - Deadlock found when trying to get lock; try restarting transaction
Почему его можно обнаружить напрямую? Это связано с тем, что возникновение взаимоблокировки должно соответствовать определенным условиям, поэтому, когда возникает взаимоблокировка, InnoDB обычно может автоматически обнаруживать ее с помощью алгоритма (графика ожидания).
Итак, какие условия должны быть выполнены для взаимоблокировки? Условия взаимоблокировки:
Потому что сам замок взаимоисключающий (1) Одновременно блокировку может удерживать только одна транзакция; (2) Другие транзакции должны получить блокировку после того, как транзакция снимает блокировку, и их нельзя принудительно лишить; (3) Когда несколько транзакций образуют цикл ожидания, возникает взаимоблокировка.
Пример:
В парикмахерской два директора. Один директор Тони по стрижке и один директор Кельвин по шампуню.
Тони не может стричь двух людей одновременно, это называется взаимное исключение.
Когда Тони стрижет кому-то волосы, вы не можете попросить его остановиться и подстричь вам волосы, это называется ненасильственное лишение. Если клиент Тони говорит директору Кельвину: как я могу подстричься, если ты не моешь мне голову? Клиент Кельвина сказал директору Тони: Как я могу мыть волосы, если вы не подстригли их для меня? Это называется формированием цикла ожидания.
Если блокировка не снята, это может привести к большому количеству блокировок или взаимоблокировок, что приведет к снижению пропускной способности системы.В это время необходимо проверить, какие транзакции удерживают блокировку.
Просмотр информации о блокировке (журнал)
Команда SHOW STATUS включает некоторую информацию о блокировке строк:
show status like 'innodb_row_lock_%';
- Innodb_row_lock_current_waits: количество ожидающих в данный момент блокировок;
- Innodb_row_lock_time : общее время от запуска системы до момента блокировки, в мс;
- Innodb_row_lock_time_avg : среднее время, затрачиваемое на каждое ожидание;
- Innodb_row_lock_time_max: время ожидания самого длительного времени с момента запуска системы;
- Innodb_row_lock_waits : общее количество ожиданий с момента запуска системы до настоящего момента.
Команда SHOW представляет собой сводное сообщение. InnoDB также предоставляет три таблицы для анализа транзакций и блокировок:
select * from information_schema.INNODB_TRX; -- 当前运行的所有事务 ,还有具体的语句
select * from information_schema.INNODB_LOCKS; -- 当前出现的锁
select * from information_schema.INNODB_LOCK_WAITS; -- 锁等待的对应关系
Как насчет того, чтобы узнать, какая транзакция удерживает блокировку?
Если транзакция удерживает блокировку в течение длительного времени и не освобождает ее, вы можете убить идентификатор потока, соответствующий транзакции, который является trx_mysql_thread_id в таблице INNODB_TRX, например, выполнить kill 4, kill 7 и kill 8.
Конечно, проблему взаимоблокировки нельзя решить, каждый раз убивая потоки. Мы должны стараться избегать этого на стороне приложения, то есть в процессе кодирования.
Какие есть способы избежать взаимоблокировок?
Предотвращение взаимоблокировки
- В программе при работе с несколькими таблицами старайтесь обращаться к ним в одном порядке (во избежание образования цикла ожидания);
- При работе с данными одной таблицы в пакетах сначала сортируйте данные (во избежание образования цикла ожидания);
- Подайте заявку на достаточный уровень блокировки, если вы хотите оперировать данными, подайте заявку на монопольную блокировку;
- Старайтесь использовать индексы для доступа к данным, избегайте операций без условий where и избегайте блокировки таблиц;
- По возможности превращайте большие сделки в маленькие;
- Используйте эквивалентный запрос вместо запроса диапазона, чтобы запросить данные, попасть в записи и избежать влияния блокировок пробелов на параллелизм.
By the way
Что-то не так? Вы можете оставить мне сообщение или приватный чат Есть урожай? Тогда поставь мне палец вверх~
Конечно, вы также можете зайти на «6 Xixuan» под моим официальным аккаунтом,
Ответьте «Узнать», чтобы получить копию[Видеоруководство для Java-инженеров и продвинутых архитекторов]~
Ответ на "интервью" вы можете получить:[Вопросы для интервью по Java, с которыми я тщательно разобрался]
Ответ на "карту мозга MySQL", вы можете получить[Очки знаний MySQL, прочесывающие карту мозга в высоком разрешении]
Поскольку я программист с профессиональным образованием, я делал это на php, Android и железе, но в итоге решил сосредоточиться на Java, поэтому, если у вас есть какие-либо вопросы, вы можете задать их и обсудить в публичном аккаунте (вы можно поговорить о технических эмоциях хахаха) см. Если вы приедете, я отвечу как можно скорее. Надеюсь учиться и прогрессировать вместе с вами. Статьи о серверной архитектуре, анализе основных знаний Java, карьере, резюме интервью и т. д. будет продолжать время от времени нажимать вывод.Приглашаем всех обратить внимание~~~