Однажды днем, добавляя поле в небольшую онлайн-таблицу, я обнаружил, что его нельзя добавить, и оно продолжало зависать. Внезапно ко мне подошел одноклассник по эксплуатации и обслуживанию и сказал, что онлайн-база данных перезагружается уже полчаса, и спросил, не сделал ли я что-нибудь. Я тогда был в шоке, а есть проблема с добавлением поля в маленькую таблицу всего более 100 строк? Я немедленно прекратил попытки добавлять поля, и, конечно же, база данных вернулась в нормальное состояние. Причина была найдена позже, поля добавились плавно, а теперь подведем итоги.
Сначала поговорим о причинах: хотя объем данных в таблице небольшой, это горячая таблица с особенно высокой частотой обращения, а доступ к таблице осуществляется в крупной транзакции. При добавлении полей ожидалось получение блокировки записи MDL. Это ожидание также влияет на получение блокировок чтения MDL для последующих обращений к таблице, вызывая блокировку последующих запросов. Что еще хуже, у клиента есть механизм повтора: если блок запроса превышает время ожидания, сеанс будет открыт для выполнения запроса, что приведет к быстрому заполнению пула потоков базы данных и непосредственному зависанию.
Что такое блокировка MDL
Блокировки MDL — это блокировки метаданных на уровне таблицы. Блокировки на уровне таблицы делятся на блокировки данных и блокировки метаданных.Обычно блокировка, которую мы говорим, обычно относится к добавленной блокировке данных. Как и блокировки данных, блокировки метаданных делятся на блокировки чтения и блокировки чтения-записи.
MDL не нужно использовать явно, он будет добавлен автоматически при выполнении табличных операций. При добавлении, удалении, изменении и запросе таблицы автоматически добавляется блокировка чтения MDL, при изменении структуры полей сложения и вычитания автоматически добавляется блокировка записи MDL.
-
Блокировки чтения не являются взаимоисключающими, что означает, что несколько потоков могут одновременно добавлять, удалять, изменять и запрашивать таблицу.
-
Блокировка записи является монопольной.Прежде чем изменять структуру, вы должны дождаться снятия всех других блокировок MDL, прежде чем получить блокировку записи MDL. После получения блокировки записи другие потоки не могут получить блокировку чтения MDL и блокировку записи до тех пор, пока блокировка записи не будет снята. То есть в процессе изменения структуры таблицы другие потоки будут блокировать работу таблицы.
Необходимость замков MDL
Существование блокировок MDL на самом деле предназначено для обеспечения согласованности данных. Представьте, что если нет MDL-блокировки, пока запрос проходит по данным таблицы, выполняется другой поток.ALTER TABLE t DELETE COLUMN 'col_1'Пучокcol_1Если этот столбец удалить, то результат запроса будет испорчен Должен ли быть этот столбец данных в результате?
повторение аварии
После введения блокировки MDL снова воспроизведем аварию. Мы моделируем онлайн-ситуацию со следующей последовательностью операций.
В момент времени 1 транзакция 1 запрашивает таблицу t_mdl_test.Обратите внимание, что транзакция 1 в это время не зафиксирована, поэтому полученная блокировка чтения MDL не будет снята. момент 2 другой поток хочет добавить поляc, Поскольку транзакция 1 удерживает блокировку чтения MDL, транзакция 2 будет заблокирована, ожидая, пока транзакция 1 освободит блокировку чтения и получит блокировку записи MDL.
Операция подачи заявки на блокировку MDL сформирует очередь, в которой блокировка записи имеет более высокий приоритет, чем блокировка чтения. Поэтому транзакция 2 блокирует не только операцию добавления полей, но и блокирует все последующие операции над таблицей. Например, следующие запросы транзакции 3 и транзакции 4 заблокированы, так как невозможно получить блокировку чтения MDL.
В настоящее время, если у клиента есть механизм повторных попыток, запрос будет повторно запрошен после истечения времени ожидания запроса, что может привести к переполнению пула соединений с базой данных.
Таблица сборки t_mdl_test:
CREATE TABLE `t_mdl_test` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id', `a` varchar(64) NOT NULL, `b` varchar(64) NOT NULL, PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8;Читатели могут обратить внимание на официальный аккаунт [игровой код] в полученной библиотеке письма.
huiwan_write_xсамостоятельный эксперимент.
Решение
После понимания причины все становится проще.Причина сбоя базы данных в том, что время ожидания добавления полей слишком велико, что влияет на последующие запросы, но mysql не можетalter tableВремя ожидания указывается в заявлении.
Таким образом, практика в то время заключалась в том, чтобы продолжать попытки добавить операторы поля и вручную отменить оператор после того, как он застрял на 30 секунд. Избегайте влияния на последующие запросы. Пробовал несколько раз и обнаружил, что его нельзя добавить. . . , и, наконец, просмотром мониторинга вызовов интерфейса, который добавляется в то время, когда частота запросов низкая.
отражение
- Избегайте записи больших транзакций.Если транзакция, в которой находится запрос, не слишком велика, это не приведет к тому, что последующие операторы не смогут получить блокировку записи MDL.
- В транзакции постарайтесь максимально сократить время блокировки. В этом примере данные, полученные от t_mdl_test, будут использоваться только при обновлении других таблиц на последнем шаге транзакции, поэтому запрос t_mdl_test можно разместить в конце транзакции. Уменьшить время блокировки t_mdl_test.
- Заявление о изменениях структуры таблицы Обратите внимание на время выполнения, давно следует отметить, что застрял для отмены, чтобы не влиять на другие добавления потоков и удаления в таблицу, чтобы изменить работу поиска.
Оставив небольшую проблему
При поиске данных я обнаружил еще одну ситуацию.Будет ли в этом случае блокироваться транзакция 2? Каждый может по-своему
huiwan_write_xПоэкспериментируйте в библиотеке самостоятельно. Я оставлю сообщение под статьей публичного аккаунта, чтобы объявить причину, и все желающие могут принять участие в обсуждении~.
напиши в конце
Друзья, которым понравилась эта статья, приглашаем обратить внимание на публичный аккаунт «Знаем, как играть в код», в котором основное внимание уделяется обмену практическими приемами на родном языке.
Благосостояние общественного счета
Ответить на [MySQL] Получить бесплатную тестовую базу данных! !
Ответьте на [pdf], чтобы получать постоянные обновления обширных учебных материалов! !