способ предотвратить запросы от ожидания блокировки на уровне таблицы

10

Мы столкнулись с проблемой после перемещения базы данных нашего клиента на дополнительный сервер. Это должно было оказать положительное влияние на производительность сайта, но есть проблема с блокировкой таблицы в MyISAM. (Я слышал об использовании InnoDB вместо MyISAM, но мы не можем изменить движок в ближайшем будущем).
Мы могли бы заметить это по запросу на обновление, который выполняется, когда модератор активирует комментарий на сайте. Это процесс:

  • обработан запрос на обновление SET status = 1 WHERE id = 5(индекс установлен)
  • кэшированные файлы страницы удалены

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

1. Я не понимаю, почему это обновление таблицы article_commentsможет повлиять на операторы выбора для таблицы, ожидающей articleблокировки на уровне таблицы. В списке процессов почти все ожидающие запросы были из этой таблицы. Я читал о том, что обновления / вставки предпочтительнее, чем выбор, и что это может вызвать такие проблемы, но сама таблица статей не обновляется при активации комментариев, поэтому выбор не должен ждать. Я неправильно понял это?
2. Есть ли что-то кроме изменения InnoDB, чтобы предотвратить это поведение или, по крайней мере, получить лучший баланс? Меня очень раздражает тот факт, что эта проблема не появилась до переноса базы данных на новый сервер. Я предполагаю, что есть некоторая неправильная конфигурация, но я не знаю, как идентифицировать.

32bitfloat
источник
1
Включите общее ведение журнала и следите за операторами JOIN между этими таблицами. Когда вы выбираете, он создает неявную блокировку чтения. Поскольку MYISAM не поддерживает блокировку на уровне строк, она блокируется на уровне таблицы. Вероятно, это тот случай, когда эта блокировка происходила на старом сервере, но никто не смотрел? Сравните строку my.cnf для строки между хостами и особенно убедитесь, что ваш key_buffer настроен правильно.
randomx
У нас было несколько других проблем с производительностью на старом сервере, и мы часто просматривали список процессов. В основном было много спящих процессов, но мы никогда не замечали ожидающих (я обычно видел эту информацию впервые на этом новом сервере). Мой парень скопировал старый my.cnf и настроил значения для нового существующего оборудования, но записей было немного. Я также сравнил результаты «SHOW VARIABLES», но не знал, что искать. Завтра мы перепроверим буфер ключей, спасибо за ваш комментарий.
32bitfloat
У нас недавно была похожая проблема. Изначально наш key_buffer_sizeбыл настроен на 1GB. Увеличение этого, чтобы 10GBуменьшить проблему.
Халук
@ Рик Джеймс, спасибо. Вы спасли меня много проблем сегодня. У вас есть список пожеланий в Amazon или где-то еще? :) Я установил query_cache_limit на 1024. Теперь нет проблем с блокировкой. Я сделал это в переменных сначала из клиента MySQL. установить глобальный query_cache_limit = 1024; Теперь я напишу это в my.cnf. Это решение позволило мне спланировать миграцию innodb без какого-либо стресса, так что спасибо.

Ответы:

8

MyISAM Storage Engine чрезвычайно известен тем, что выполняет полные блокировки таблиц для любого DML (INSERT, UPDATEs, DELETEs). InnoDB определенно решит эту проблему в долгосрочной перспективе.

Я писал о плюсах и минусах использования MyISAM против InnoDB

Что касается вашего текущего вопроса, вот возможный сценарий:

  • articleи article_commentsобе таблицы MyISAM
  • article_commentsимеет один или несколько индексов statusв качестве столбца
  • Обновления страницы индекса для article_commentsкэшируются в буфере ключа MyISAM (размер по ключу key_buffer_size ), в результате чего старые страницы индекса выходят из буфера ключа MyISAM
  • У вас есть запросы SELECT, которые выполняют соединения между articleиarticle_comments

В моем предложенном сценарии SELECTs для articleтаблицы могут быть запрещены для записи из-за необходимости ждать article_commentsосвобождения от любого DML (в данном случае, an UPDATE)

RolandoMySQLDBA
источник
Спасибо за ваш ответ (и ссылки), ваш сценарий реален. Я не осознавал, что большинство избранных статей действительно присоединяются к таблице комментариев (или, другими словами, видели неполные утверждения в списке процессов phpmyadmin). Знаете ли вы краткосрочное решение для предотвращения нескольких ожидающих запросов? Я уже пробовал это с «UPDATE LOW_PRIORITY» в конкретном утверждении, но это не внесло заметных изменений. В будущем мы действительно перейдем на innodb, но мне интересно, есть ли способ добиться улучшения в настоящее время.
32bitfloat
Конечное решение: конвертировать таблицы в InnoDB. Смотрите мой пост dba.stackexchange.com/a/9422/877 о том, как конвертировать все MyISAM в InnoDB
RolandoMySQLDBA
7

На этом этапе вся страница становится медленной. Сама база данных занята в течение нескольких минут.

Пахнет, как будто у тебя большой Query_cache?

mysql> SHOW VARIABLES LIKE 'query_cache%';
+------------------------------+----------+
| Variable_name                | Value    |
+------------------------------+----------+
| query_cache_limit            | 1048576  |
| query_cache_min_res_unit     | 4096     |
| query_cache_size             | 16777216 | -- Not over 50M
| query_cache_type             | DEMAND   | -- Only if using SQL_CACHE
| query_cache_wlock_invalidate | OFF      |
+------------------------------+----------+

Для производственных систем с большим количеством записей вы также можете отключить query_cache.

Все записи в query_cache для данной таблицы очищаются при любой записи в эту таблицу. Чем больше КК, тем медленнее эта задача.

MyISAM использует блокировки на уровне таблицы. Чтение и запись не могут происходить одновременно (в одной таблице). Грубый, но эффективный.

Рик Джеймс
источник
1
Ну да. У нас около 64M кэширования. Спасибо за эту информацию, которая была новой для меня, однако, у нас было то же значение на старом сервере, где мы не замечали блокировки таблиц. Мы уже начали переходить на InnoDB, но этот факт остается загадкой ...
32bitfloat