Задавайте вопросы, мы ответим
Вы не зашли.
Здравствуйте. Последнее время выделенный Debian Linux сервер с MySql 5.1 быстро уходит в swap, уменьшение параметров потребления памяти не помогает.
У сервера на борту имеется 8 ГБ оперативной памяти.
Для баз данных используется Innodb.
К mysql серверу постоянно подключены ~100 пользователей. Если сложить innodb_buffer_pool_size(2000) + max_connections(300) * (thread_stack(0,5) + read_buffer_size(1) + join_buffer_size(2) + read_rnd_buffer_size(1) + sort_buffer_size(1)), то получится 3650МБ. При чем количество подключений больше 200 точно не поднимается, а память все равно куда-то уходит, причем не возвращается обратно. К примеру с приведенной конфигурацией mysql через неделю уже потреблял больше 9 ГБ памяти.
Не можем понять куда уходит память, помогите разобраться пожалуйста. Может как-то можно понять, на что mysql расходует память.
Конфиг СУБД следующий:
[mysqld]
lower_case_table_names = 1
skip-name-resolve
skip-external-locking
event_scheduler = ON
old_passwords = 1
key_buffer = 16M
max_allowed_packet = 60M
thread_stack = 528K
thread_cache_size = 20
myisam-recover = BACKUP
max_connections = 300
query_cache_limit = 1M
query_cache_size = 16M
query_cache_type = 2
expire_logs_days = 10
max_binlog_size = 500M
innodb_log_buffer_size = 5M
default-character-set=utf8
default-storage-engine=INNODB
innodb_file_per_table
innodb_flush_log_at_trx_commit = 0
innodb_buffer_pool_size = 2G
tmp_table_size = 50M
max_heap_table_size = 30M
key_buffer_size = 50M
table_open_cache = 700
table_definition_cache = 1500
read_buffer_size = 1M
innodb_additional_mem_pool_size = 5M
join_buffer_size = 2M
read_rnd_buffer_size = 1M
max_tmp_tables = 128
sort_buffer_size = 1M
federated
Неактивен
Может быть утечка памяти в конкретно вашей версии. Попробуйте обновить на 5.5
Неактивен
Переход на 5.5 это крайняя мера. Для начала хотелось бы определиться все ли мы учли. Может mysql еще куда-то выделяет память кроме вышеперечисленных буферов? Есть ли какие либо точные формулы расчета? Есть ли какие возможности посмотреть в самом mysql как распределена память? Отдельным вопросом стоит если к примеру клиент не закрыл рекордсет и закрыл подключение к базе, может ли это повлиять на утечку памяти?
Неактивен
Клиентское поведение не должно приводить к утечкам на сервере. После закрытия соединения, все связанные с ним буферы освобождаются.
Вы привели достаточно разумную формулу для оценки используемой памяти. К ней можно добавить query_cache_size+key_buffer, но это несущественно в вашей конфигурации. Еще нужно проверить нет ли таблиц типа MEMORY.
Дополнительный вопрос: это плохо, что MySQL попадает в своп? То есть он просто забивает своп неиспользуемыми (потерянными) областями памяти или он к свопу непрерывно обращается?
Неактивен
Точные данные по интенсивности использования свопа не смотрели (надо все таки посмотреть), но видимо использование идет интенсивно, потому что жалуются пользователи, что клиентское ПО начинает все медленнее и медленнее работать. Из-за жалоб пользователей-то мы и обратили внимание на своп.
А как проверить таблицы типа MEMORY? Руками мы их точно не создаем, теоретически они могут иногда создаваться при выполнении некоторых процедур как временные таблицы, но временные таблицы должны же удалится, после выполнения запроса ну или после закрытия коннекта.
А существуют какие либо утилиты, которые могут залезть в mysql и сказать на что распределяет память в конкретный момент времени?
Неактивен
Утилиты профилирования внутренней памяти mysql мне неизвестны.
Кстати, обратил внимание на два параметра
tmp_table_size = 50M
max_heap_table_size = 30M
С одной стороны нет смысла делать tmp_table_size > max_heap_table_size ( http://dev.mysql.com/doc/refman/5.5/en/ … table_size ), в этом случае ограничителем будет второй параметр. С другой стороны вы не учли в формуле возможные созданные при исполнении запроса временные таблицы. Эти таблицы, конечно, при завершении запроса высвобождаются. Кстати, в 5.5 есть performance_schema, которая позволяет просматривать некоторую (не всю) информацию о работе сервера.
Неактивен
Вот еще два предположения: event scheduler и federated. Первое может
порождать потоки помимо тех соединений, которые есть честные внешние
соединения (а буферы выделяет). Второе склонно материализовывать в
памяти внешние таблички, что тоже может плохо сказываться на памяти.
Неактивен
tmp_table_size и max_heap_table_size привели в соответствие, спасибо.
event scheduler используется только по ночам и в рабочее время не должен кому-то мешать.
federated используется тоже не постоянно и после использования таблицы удаляются. Посмотрел через information_schema таблицы, в момент нахождения в глубоком свопе не было не одной federated таблицы.
Еще раз понаблюдали на одну из ситуаций, при которой появился своп. Запрос блокирует какой-то ресурс, скапливается несколько десятков запросов, которые ждут освобождения ресурса, происходит резкое увеличение потребления памяти, такими темпами база уходит в своп. Все вроде логично. Но потом очередь запросов опустошается, а вот потребление памяти не уменьшается и своп меньше не становится. С помощью vmstat смотрим ввод/вывод свопа, вроде нет активного его использование, но иногда есть кратковременные всплески. Затем запустили еще запрос, который застопорил выполнение других запросов. Своп продолжил набирать обороты. Когда очередь запросов опустошилась, ввод/вывод свопа в этот раз уже продолжал быть активным в течении приличного промежутка времени и размер свопа в итоге не уменьшился.
Потребление памяти смотрим в столбце VIRT команды top. Может что-то не так смотрим? Почему потребление памяти только растет и не уменьшается?
Неактивен
VIRT не та колонка, которую надо смотреть - это просто объем адресного пространства, а не используемой памяти. Стоит смотреть колонку RES. Что касается свопа все выглядит нормально - при большом количестве запросов MySQL использует своп, а потом своп не освобождается, но это поведение системы linux - нет смысла его освобождать физически, если в нем что-то, что не используется.
Думаю вам стоит сконцентрироваться на оптимизации запросов, которые лочат другие. Ясно, что при нарастании одновременных запросов использование памяти нарастает, но в ситуации, когда запросов в очереди нет, это не создаст вам проблемы.
Неактивен
Почитал про столбец VIRT, вроде как рассчитывается как RES + SWAP. Даже если предположим, что для Linux является нормальным выделить адресное пространство в свопе и не освобождать, когда приложению больше не требуется столько памяти, то почему значение столбца RES тоже никогда не уменьшается. Или оно тоже показывает только выделенное адресное пространство и не показывает сколько в реальности потребляет приложение?
Неактивен