Для начала несколько подробностей, чтобы описать ситуацию в целом:
- База данных MySQL (5.1.50) на очень мощной (32 ядра процессора, 64 ГБ ОЗУ) машине FreeBSD 8.1-RELEASEна котором также работает Apache 2.2.
- Apache получает в среднем около 50 обращений в секунду.Подавляющее большинство из этих хитов - это вызовы API для платформы продажи.
- Вызовы API обычно генерируют результат примерно за полсекунды или меньше, но могут занять до 30 секунд в зависимости от сторонних производителей.
- Каждый из вызовов API сохраняет строку в базе данных.Сохраненная там информация важна, но только в течение пятнадцати минут, после чего она должна истечь.
- В таблице, в которой хранится информация о вызовах API (схема приведена ниже), InnoDB на уровне строкБлокировка используется для синхронизации между потоками (на самом деле соединения Apache), запрашивающими одну и ту же информацию в одно и то же время, что часто случается.Это означает, что несколько потоков могут ожидать блокировки строки до 30 секунд , поскольку вызовы API могут занять столько времени (но обычно этого не происходит).
- Прежде всего, самое важное, что следует отметить, это то, что все работает идеально при нормальных обстоятельствах.
Тем не менее, это очень часто используемая таблица (пятьдесят или около того INSERT в секунду, много SELECT, используется блокировка на уровне строк) Я выполняю запрос DELETE:
CREATE TABLE `sales` (
`sale_id` int(32) unsigned NOT NULL auto_increment,
`start_time` int(20) unsigned NOT NULL,
`end_time` int(20) unsigned default NULL,
`identifier` char(9) NOT NULL,
`zip_code` char(5) NOT NULL,
`income` mediumint(6) unsigned NOT NULL,
PRIMARY KEY USING BTREE (`sale_id`),
UNIQUE KEY `SALE_DATA` (`ssn`,`zip_code`,`income`),
KEY `SALE_START` USING BTREE (`start_time`)
) ENGINE=InnoDB DEFAULT CHARSET=ascii ROW_FORMAT=FIXED
Запрос DELETE
выглядит следующим образом и выполняется каждые пять минут в cron (я быпредпочитаю запускать его раз в минуту):
DELETE FROM `sales` WHERE
`start_time` < UNIX_TIMESTAMP(NOW() - INTERVAL 30 MINUTE);
Я использовал INT
для поля времени, поскольку очевидно, что MySQL испытывает проблемы с использованием индексов с полями DATETIME
.
Так вот в чем проблема: запрос DELETE
, кажется, работает нормально большую часть времени (возможно, 7 из 10 раз).В других случаях запрос завершается быстро, но после этого MySQL, похоже, задыхается некоторое время.Я не могу точно доказать, что MySQL работает, но время появления симптомов определенно совпадает со временем выполнения этого запроса.Вот симптомы, когда все захлебывается:
- При входе в MySQL и использовании
SHOW FULL PROCESSLIST;
выполняется всего несколько запросов INSERT INTO
sales ...
, где обычно болеесто.Что здесь ненормально, так это отсутствие каких-либо задач в списке процессов, а не их слишком много.Похоже, что MySQL прекращает принимать соединения полностью. - Проверяя состояние сервера Apache, Apache достиг MaxClients.Все потоки находятся в состоянии «Отправка ответа».
- Apache начинает использовать много процессорного времени системы.Средние значения нагрузки увеличиваются, я видел средние значения нагрузки за 1 минуту до 100. Нормальное среднее значение нагрузки для этой машины составляет около 15. Я вижу, что она использует системный ЦП (в отличие от пользовательского ЦП), потому что я использую GKrellM для мониторингаit.
- В
top
есть много процессов Apache, использующих много ЦП. - Веб-сайт и API (обслуживаемые Apache, конечно) в большинстве случаев недоступны.Некоторые запросы выполняются, но занимают около трех или четырех минут.Другие запросы отвечают через некоторое время с ошибкой «Не удается подключиться к серверу MySQL через /tmp/mysql.sock» - это та же ошибка, что и я, когда MySQL перегружен и имеет слишком много подключений (только это не такна самом деле говорят, что слишком много подключений).
- MySQL принимает максимум 1024 подключений, mysqltuner.pl сообщает «[!!] Максимальное использование подключений: 100% (1025/1024)», что означает, что оно занято больше, чем ономог справиться в одной точке.Обычно при нормальных условиях существует не более нескольких сотен одновременных подключений MySQL.mysqltuner.pl не сообщает о других проблемах, я буду рад вставить вывод, если кто-нибудь захочет.
В конце концов, через минуту или две, все восстанавливается самостоятельно без какого-либо вмешательства.Загрузка ЦП возвращается к нормальной работе, Apache и MySQL возобновляют нормальную работу.
Итак, что я могу сделать? :) Как я могу начать расследовать, почему это происходит? Мне нужно , чтобы этот запрос DELETE выполнялся по разным причинам, почему дела идут плохо, когда он выполняется (но не всегда)?