периодический сбой MySQL с ошибкой «Неустранимая ошибка: невозможно выделить память для пула буферов»

40

Добавлено в редакцию, 2013-05-29: Поскольку это длинный вопрос и обсуждение, вот краткое резюме вопроса и решения. У меня были проблемы с запуском MySQL и Apache на небольшом сервере Linux (1 ГБ памяти). Apache требовал больше памяти, и, как следствие, ОС всегда убивала MySQL, чтобы восстановить свою память. Решением было заменить Apache на Lighttpd. После того, как я это сделал, использование памяти на сервере было полностью стабильным в течение нескольких месяцев, и у меня не было никаких сбоев любого рода. конец редактирования

Я начинающий системный администратор для небольшого виртуального сервера. Основная функция сервера - запуск программного обеспечения системы управления курсами Moodle с открытым исходным кодом, написанного на PHP. Он опирается на базу данных, в данном случае MySQL, и веб-сервер, в данном случае Apache.

Сервер работает под управлением 64-разрядной версии CentOS 5.8 (Final) с 1 ГБ памяти и 200 ГБ диска, версия ядра 2.6.18-308.8.2.el5xen. Версия MySQL Ver 14.14 Distrib 5.5.25, для Linux (x86_64) с использованием readline 5.1.

Я не думаю, что программное обеспечение Moodle является таким активным пользователем MySQL. В настоящее время только около десяти учителей имеют к нему доступ, и когда я копирую и сжимаю с помощью bzip2 всю базу данных, размер получаемого дампа составляет менее 1 МБ.

Я настроил систему несколько месяцев назад. Все это время сервер Apache был стабильным, но MySQL несколько раз падал. Я попытался узнать об оптимальной конфигурации через Интернет, и в последний раз, когда я изменял /etc/my.cnfфайл, я использовал файл, /usr/share/doc/mysql55-server-5.5.25/my-large.cnfкоторый поставляется с MySQL в качестве примера. В файле сказано, что он предназначен для систем с 512 МБ памяти, поэтому я подумал, что использование его параметров конфигурации, связанных с памятью, будет безопасным для этой системы. (Ранее я настраивал параметры MySQL, связанные с памятью, с гораздо меньшими числами, и я подумал, что это могло привести к сбоям. Хотя сбои все еще происходят, система теперь, по крайней мере, быстрее.) Это текущее содержимое /etc/my.cnf:

# /etc/my.cfg

# The main and only MySQL configuration file on [WEBSITE ADDRESS REDACTED].
# Last updated 2012-09-23 by Teemu Leisti.

# Most of the memory settings are set to be the same as the example setting file
# /usr/share/doc/mysql55-server-5.5.25/my-large.cnf, which is meant for systems
# with 512M of memory.  This server currently has twice that, i.e. 1G of memory,
# which should make these settings safe.


[client]
default_character_set           = utf8
port                            = 3306
socket                          = /var/lib/mysql/mysql.sock

[mysqld]
character_set_filesystem        = utf8
character_set_server            = utf8
datadir                         = /var/lib/mysql
innodb_additional_mem_pool_size = 20M
innodb_buffer_pool_size         = 256M # You can set .._buffer_pool_size up to
                                       # 50..80% of RAM, but beware of setting
                                       # memory usage too high
innodb_data_file_path           = ibdata1:10M:autoextend
innodb_data_home_dir            = /var/lib/mysql
innodb_flush_log_at_trx_commit  = 1
innodb_lock_wait_timeout        = 50
innodb_log_buffer_size          = 8M
innodb_log_file_size            = 64M # Set .._log_file_size to 25% of buffer
                                      # pool size
innodb_log_group_home_dir       = /var/lib/mysql
interactive_timeout             = 60
key_buffer_size                 = 256M
long_query_time                 = 10
max_allowed_packet              = 1M
max_connections                 = 30
port                            = 3306
query_cache_limit               = 2M # see http://emergent.urbanpug.com/?p=61
query_cache_size                = 16M
read_buffer_size                = 1M
read_rnd_buffer_size            = 4M
skip_networking                 # Only local processes need to use MySQL
skip_symbolic_links             # Disabling symbolic_links is recommended to
                                # prevent assorted security risks
slow_query_log_file             = /var/log/mysql-slow-queries.log
socket                          = /var/lib/mysql/mysql.sock
sort_buffer_size                = 1M
table_open_cache                = 256
thread_cache_size               = 8
thread_concurrency              = 2 #    = number of CPUs * 2
user                            = mysql
wait_timeout                    = 10

[mysqld_safe]
log_error                       = /var/log/mysqld.log
open_files_limit                = 4096
pid_file                        = /var/run/mysqld/mysqld.pid

[mysqldump]
quick
max_allowed_packet              = 16M

[mysql]
no-auto-rehash
# Remove the next comment character if you are not familiar with SQL
safe-updates

[myisamchk]
key_buffer_size                 = 128M
sort_buffer_size                = 128M
read_buffer                     = 2M
write_buffer                    = 2M

[mysqlhotcopy]
interactive-timeout

Как видно из конфигурации, в установке используется механизм InnoDB, и он обслуживает только запросы от localhost. Помимо системного администратора (я), Moodle является единственным пользователем MySQL.

Когда происходит сбой MySQL, в файл журнала неизменно записывается следующее /var/log/mysqld.log(кроме временных меток, конечно):

120926 08:00:51 mysqld_safe Number of processes running now: 0
120926 08:00:51 mysqld_safe mysqld restarted
120926  8:00:53 [Note] Plugin 'FEDERATED' is disabled.
120926  8:00:53 InnoDB: The InnoDB memory heap is disabled
120926  8:00:53 InnoDB: Mutexes and rw_locks use GCC atomic builtins
120926  8:00:53 InnoDB: Compressed tables use zlib 1.2.3
120926  8:00:53 InnoDB: Using Linux native AIO
120926  8:00:53 InnoDB: Initializing buffer pool, size = 256.0M
InnoDB: mmap(274726912 bytes) failed; errno 12
120926  8:00:53 InnoDB: Completed initialization of buffer pool
120926  8:00:53 InnoDB: Fatal error: cannot allocate memory for the buffer pool
120926  8:00:53 [ERROR] Plugin 'InnoDB' init function returned error.
120926  8:00:53 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
120926  8:00:53 [ERROR] Unknown/unsupported storage engine: InnoDB
120926  8:00:53 [ERROR] Aborting

120926  8:00:53 [Note] /usr/libexec/mysqld: Shutdown complete

120926 08:00:53 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended

Иногда я могу перезапустить MySQL командиров service mysqld restart, но иногда , что команда не с этим выходом: mysqld dead but subsys locked. В этих случаях единственное, что я смог придумать, чтобы восстановить ситуацию, это перезапустить сервер, после чего MySQL может быть перезапущен. В этих случаях вывод выглядит так:

120926 11:43:48 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql
120926 11:43:48 [Note] Plugin 'FEDERATED' is disabled.
120926 11:43:48 InnoDB: The InnoDB memory heap is disabled
120926 11:43:48 InnoDB: Mutexes and rw_locks use GCC atomic builtins
120926 11:43:48 InnoDB: Compressed tables use zlib 1.2.3
120926 11:43:48 InnoDB: Using Linux native AIO
120926 11:43:48 InnoDB: Initializing buffer pool, size = 256.0M
120926 11:43:48 InnoDB: Completed initialization of buffer pool
120926 11:43:48 InnoDB: highest supported file format is Barracuda.
InnoDB: The log sequence number in ibdata files does not match
InnoDB: the log sequence number in the ib_logfiles!
120926 11:43:48  InnoDB: Database was not shut down normally!
InnoDB: Starting crash recovery.
InnoDB: Reading tablespace information from the .ibd files...
InnoDB: Restoring possible half-written data pages from the doublewrite
InnoDB: buffer...
120926 11:43:51  InnoDB: Waiting for the background threads to start
120926 11:43:52 InnoDB: 1.1.8 started; log sequence number 466807107
120926 11:43:52 [Note] Event Scheduler: Loaded 0 events
120926 11:43:52 [Note] /usr/libexec/mysqld: ready for connections.
Version: '5.5.25'  socket: '/var/lib/mysql/mysql.sock'  port: 0  MySQL Community Server (GPL)

Вот что команда free -mвыводит в данный момент:

# free -m
             total       used       free     shared    buffers     cached
Mem:          1024        869        154          0         70        153
-/+ buffers/cache:        644        379
Swap:            0          0          0

Обычно «свободный» столбец составляет от 50 до 100 МБ.

Вывод команды ulimit -a:

# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 8192
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 8192
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Я не изменил ни один из файлов настроек или кодов Moodle, за исключением того /var/www/html/moodle/config.php, что выглядит так (строки комментариев удалены для экономии места):

<?php
unset($CFG);  // Ignore this line
global $CFG;  // This is necessary here for PHPUnit execution
$CFG = new stdClass();
$CFG->dbtype    = 'mysqli';           // 'pgsql', 'mysqli', 'mssql', 'sqlsrv' or 'oci'
$CFG->dblibrary = 'native';           // 'native' only at the moment
$CFG->dbhost    = 'localhost';        // eg 'localhost' or 'db.isp.com' or IP
$CFG->dbname    = 'moodle';           // database name, eg moodle
$CFG->dbuser    = 'moodleuser';       // your database username
$CFG->dbpass    = '[REDACTED]';       // your database password
$CFG->prefix    = 'moodle_';          // prefix to use for all table names
$CFG->dboptions = array(
    'dbpersist' => false,       // should persistent database connections be
                                //  used? set to 'false' for the most stable
                                //  setting, 'true' can improve performance
                                //  sometimes
    'dbsocket'  => true,        // should connection via UNIX socket be used?
                                //  if you set it to 'true' or custom path
                                //  here set dbhost to 'localhost',
                                //  (please note mysql is always using socket
                                //  if dbhost is 'localhost' - if you need
                                //  local port connection use '127.0.0.1')
    'dbport'    => '',          // the TCP port number to use when connecting
                                //  to the server. keep empty string for the
                                //  default port
);
$CFG->passwordsaltmain = '[REDACTED]';
$CFG->wwwroot   = 'http://[REDACTED]';
$CFG->dataroot  = '/var/moodledata';
$CFG->directorypermissions = 02777;
$CFG->admin = 'admin';
date_default_timezone_set('Europe/Helsinki');
$CFG->disableupdatenotifications = true;
require_once(dirname(__FILE__) . '/lib/setup.php'); // Do not edit

(Однако я установил два плагина Moodle, модуль посещаемости и блок , но я не понимаю, как они могут быть связаны с этой проблемой.)

Даже после того, как я обновил /etc/my.cnfсвое текущее состояние неделю назад, MySQL несколько раз ломался с симптомами, приведенными выше. Будучи новичком в администрировании баз данных, и, после долгих поисков этой проблемы, я не знаю, что делать дальше. Какие-либо предложения? Должен ли я публиковать больше данных конфигурации?

Дополнение по редактированию:

Содержимое файла /var/log/messages.1:

Sep 23 04:02:18 [machine name] syslogd 1.4.1: restart.
Sep 26 08:00:51 [machine name] kernel: mysqld invoked oom-killer: gfp_mask=0x201d2, order=0, oomkilladj=0
Sep 26 08:00:51 [machine name] kernel:
Sep 26 08:00:51 [machine name] kernel: Call Trace:
Sep 26 08:00:51 [machine name] kernel:  [<ffffffff802c1bd5>] out_of_memory+0x8b/0x203
Sep 26 08:00:51 [machine name] kernel:  [<ffffffff8020fa49>] __alloc_pages+0x27f/0x308
Sep 26 08:00:51 [machine name] kernel:  [<ffffffff802139c9>] __do_page_cache_readahead+0xc8/0x1af
Sep 26 08:00:51 [machine name] kernel:  [<ffffffff8021423a>] filemap_nopage+0x14c/0x360
Sep 26 08:00:51 [machine name] kernel:  [<ffffffff80208e9d>] __handle_mm_fault+0x444/0x144f
Sep 26 08:00:51 [machine name] kernel:  [<ffffffff80263929>] _spin_lock_irqsave+0x9/0x14
Sep 26 08:00:51 [machine name] kernel:  [<ffffffff8023f468>] lock_timer_base+0x1b/0x3c
Sep 26 08:00:51 [machine name] kernel:  [<ffffffff80266d94>] do_page_fault+0xf72/0x131b
Sep 26 08:00:51 [machine name] kernel:  [<ffffffff802e5f4f>] sys_io_getevents+0x311/0x359
Sep 26 08:00:51 [machine name] kernel:  [<ffffffff802e4e56>] timeout_func+0x0/0x10
Sep 26 08:00:51 [machine name] kernel:  [<ffffffff8025f82b>] error_exit+0x0/0x6e
Sep 26 08:00:51 [machine name] kernel:
Sep 26 08:00:51 [machine name] kernel: Mem-info:
Sep 26 08:00:51 [machine name] kernel: DMA per-cpu:
Sep 26 08:00:51 [machine name] kernel: cpu 0 hot: high 0, batch 1 used:0
Sep 26 08:00:51 [machine name] kernel: cpu 0 cold: high 0, batch 1 used:0
Sep 26 08:00:51 [machine name] kernel: DMA32 per-cpu:
Sep 26 08:00:51 [machine name] kernel: cpu 0 hot: high 186, batch 31 used:117
Sep 26 08:00:51 [machine name] kernel: cpu 0 cold: high 62, batch 15 used:53
Sep 26 08:00:51 [machine name] kernel: Normal per-cpu: empty
Sep 26 08:00:51 [machine name] kernel: HighMem per-cpu: empty
Sep 26 08:00:51 [machine name] kernel: Free pages:        7256kB (0kB HighMem)
Sep 26 08:00:51 [machine name] kernel: Active:241649 inactive:0 dirty:0 writeback:0 unstable:0 free:1814 slab:4104 mapped-file:1153 mapped-anon:240592 pagetables:3298
Sep 26 08:00:51 [machine name] kernel: DMA free:3268kB min:32kB low:40kB high:48kB active:0kB inactive:0kB present:9068kB pages_scanned:0 all_unreclaimable? yes
Sep 26 08:00:51 [machine name] kernel: lowmem_reserve[]: 0 994 994 994
Sep 26 08:00:51 [machine name] kernel: DMA32 free:3988kB min:4016kB low:5020kB high:6024kB active:966596kB inactive:0kB present:1018080kB pages_scanned:6327262 all_unreclaimable? yes
Sep 26 08:00:52 [machine name] kernel: lowmem_reserve[]: 0 0 0 0
Sep 26 08:00:52 [machine name] kernel: Normal free:0kB min:0kB low:0kB high:0kB active:0kB inactive:0kB present:0kB pages_scanned:0 all_unreclaimable? no
Sep 26 08:00:52 [machine name] kernel: lowmem_reserve[]: 0 0 0 0
Sep 26 08:00:52 [machine name] kernel: HighMem free:0kB min:128kB low:128kB high:128kB active:0kB inactive:0kB present:0kB pages_scanned:0 all_unreclaimable? no
Sep 26 08:00:52 [machine name] kernel: lowmem_reserve[]: 0 0 0 0
Sep 26 08:00:52 [machine name] kernel: DMA: 1*4kB 2*8kB 1*16kB 1*32kB 2*64kB 2*128kB 1*256kB 1*512kB 2*1024kB 0*2048kB 0*4096kB = 3268kB
Sep 26 08:00:52 [machine name] kernel: DMA32: 17*4kB 2*8kB 2*16kB 1*32kB 0*64kB 0*128kB 1*256kB 1*512kB 1*1024kB 1*2048kB 0*4096kB = 3988kB
Sep 26 08:00:52 [machine name] kernel: Normal: empty
Sep 26 08:00:52 [machine name] kernel: HighMem: empty
Sep 26 08:00:52 [machine name] kernel: 1214 pagecache pages
Sep 26 08:00:52 [machine name] kernel: Swap cache: add 0, delete 0, find 0/0, race 0+0
Sep 26 08:00:52 [machine name] kernel: Free swap  = 0kB
Sep 26 08:00:52 [machine name] kernel: Total swap = 0kB
Sep 26 08:00:52 [machine name] kernel: Free swap:            0kB
Sep 26 08:00:52 [machine name] kernel: 262144 pages of RAM
Sep 26 08:00:52 [machine name] kernel: 8320 reserved pages
Sep 26 08:00:52 [machine name] kernel: 22510 pages shared
Sep 26 08:00:52 [machine name] kernel: 0 pages swap cached
Sep 26 08:00:52 [machine name] kernel: Out of memory: Killed process 1371, UID 27, (mysqld).

а затем строки, связанные с перезагрузкой в ​​11:42.

Дополнение по редакции № 2:

Я попытался прокомментировать ответ Майкла, но я столкнулся с лимитом комментариев, поэтому я отвечаю здесь.

Спасибо за ответ, Майкл. Я только что отредактировал свой вопрос, включив в него содержимое системного журнала машины во время сбоя. (Кажется, CentOS вызывает системный журнал /var/log/messages.)

Да, как MySQL, так и системные журналы выглядят практически идентичными тем, которые вы указали в вопросе. И теперь, когда вы упомянули об этом, становится очевидно, что mysql restartedсообщение означает, что MySQL уже потерпел крах. Системный журнал указывает, что это то, oom_killerчто получил процесс. В своем предыдущем ответе вы пишете: «Первое предположение: дочерние процессы apache запускаются безрассудно». Мне кажется, что и здесь Apache является очевидным подозреваемым.

Ранее я обнаружил статью « Оптимизация MySQL и Apache для нехватки памяти», часть 1 . Для настройки Apache автор рекомендует: «Во-первых, Apache. Мое первое утверждение: если вы можете избежать этого, попробуйте. Lighttpd и thttpd оба очень хороши, без излишних веб-серверов, и вы можете запустить lighttpd с PHP. Даже если вы Если вы используете сайт с большим объемом, вы можете серьезно повысить производительность, передав статический контент (обычно изображения и файлы javascript) на легкий сверхбыстрый HTTPd-сервер, такой как Lighttpd. "

Я подумываю о совете автора и согласился с моим клиентом, что на следующих выходных я заменю Apache на Lighttpd на сервере. Я надеюсь, что это решит проблемы. Использование двух виртуальных серверов, скорее всего, невозможно.

Я не думал, что использование двух стабильных, зрелых серверов с открытым исходным кодом, таких как MySQL и Apache на одной машине, с разумным объемом памяти будет проблематичным.

Теему Лейсти
источник

Ответы:

36

Пожалуйста, просмотрите мой ответ на этот недавний вопрос . Я считаю, что обстоятельства идентичны.

Не изменяйте свою конфигурацию MySQL на этом этапе, поскольку MySQL не является проблемой - это только симптом проблемы ... которая заключается в том, что у вас, похоже, есть система с небольшим объемом памяти и нулевым пространством подкачки.

Ваш сервер не падает, потому что память не может быть выделена для пула буферов. Ваш сервер выходит из строя ... и затем не может быть перезапущен из-за недоступности системной памяти. Вся память, сконфигурированная для пула буферов InnoDB, запрашивается системой при запуске mysql.

Когда вы видите это сообщение журнала ...

120926 08:00:51 mysqld_safe Number of processes running now: 0

... ваш сервер уже умер. Если до этого ничего не регистрировалось, ничего о первом сбое не будет регистрироваться. Последующие журналы происходят после автоматической попытки перезапуска.

Проверьте системный журнал, и вы должны найти сообщения, в которых ядро ​​отправлялось на поиски процессов, которые нужно убить из-за экстремального состояния нехватки памяти.

Шаг 1, вероятно, заключался бы в добавлении некоторого пространства подкачки и / или выделения ОЗУ, если это вообще возможно.

Если это невозможно, вы можете подумать об уменьшении размера innodb-buffer-pool в вашей конфигурации. (Я никогда не думал, что на самом деле слышу, как я сам так говорю). Пока ваша база данных мала и ваш трафик мал, вам может не понадобиться такой большой буферный пул ... и поскольку память пула буферов InnoDB все выделяется при запуске, независимо от того, нужна она или нет, это освободит некоторые ваши ресурсы. Системная память для всего остального требует этого. (Рекомендация от 75% до 80% общего объема ОЗУ для определения размера пула буферов верна, только если весь сервер выделен для MySQL.)

Шаг 2 будет посвящен рассмотрению модели разветвления Apache и того, что вам может понадобиться сделать по-другому в конфигурации, чтобы предотвратить перегрузку вашего сервера. Вполне вероятно, что неконтролируемый рост количества или требований к памяти дочерних процессов Apache запускает каскад событий, в результате чего ядро ​​убивает MySQL, пытаясь избежать полного сбоя всего сервера.

В зависимости от вашей гибкости, вы можете даже рассмотреть две отдельные виртуальные машины для Apache и MySQL.

Майкл - sqlbot
источник