MySQL intermittente si arresta in modo anomalo con errore "Errore irreversibile: impossibile allocare memoria per il pool di buffer"


40

Aggiunto in modifica, 29/05/2013: poiché questa è una lunga domanda e discussione, ecco un breve riassunto della domanda e della soluzione. Ho avuto problemi con MySQL e Apache su un piccolo server Linux (1 GB di memoria). Apache ha continuato a richiedere più memoria e, di conseguenza, il sistema operativo ha sempre ucciso MySQL per riguadagnare memoria. La soluzione era sostituire Apache con Lighttpd. Dopo averlo fatto, l'uso della memoria sul server è stato completamente stabile per diversi mesi e non ho avuto crash di alcun tipo. fine della modifica

Sono un amministratore di sistema principiante per un piccolo server virtuale. La funzione principale del server è eseguire il software open source Moodle per la gestione dei corsi, scritto in PHP. Si basa su un database, in questo caso MySQL, e un server Web, in questo caso Apache.

Il server esegue CentOS versione 5.8 (Final) a 64 bit con 1 GB di memoria e 200 GB di disco, versione 2.6.18-308.8.2.el5xen del kernel. La versione di MySQL è la Ver 14.14 Distrib 5.5.25, per Linux (x86_64) usando readline 5.1.

Non penso che il software Moodle sia un utente così pesante di MySQL. Attualmente, solo una decina di insegnanti possono accedervi e quando eseguo il dump e comprimo con bzip2 l'intero database, la dimensione del dump risultante è inferiore a 1 MB.

Ho installato il sistema alcuni mesi fa. Il server Apache è rimasto stabile per tutto questo tempo, ma MySQL si è bloccato più volte. Ho provato a conoscere la configurazione ottimale dal web e l'ultima volta che ho cambiato il /etc/my.cnffile, ho usato il file /usr/share/doc/mysql55-server-5.5.25/my-large.cnffornito con MySQL come esempio. Il file dice che è pensato per sistemi con 512 MB di memoria, quindi ho pensato che l'uso dei suoi parametri di configurazione relativi alla memoria sarebbe stato sicuro per questo sistema. (In precedenza avevo configurato i parametri relativi alla memoria di MySQL con numeri molto più piccoli e pensavo che ciò avrebbe potuto portare agli arresti anomali. Mentre gli arresti anomali si verificano ancora, il sistema è almeno più veloce ora.) Questi sono i contenuti attuali di /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

Come puoi vedere nella configurazione, l'installazione usa il motore InnoDB e serve solo le richieste da localhost. A parte l'amministratore di sistema (me), Moodle è l'unico utente di MySQL.

Quando MySQL si arresta in modo anomalo, quanto segue viene invariabilmente scritto nel file di registro /var/log/mysqld.log(ad eccezione dei timestamp, ovviamente):

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

A volte posso riavviare MySQL comandando service mysqld restart, ma a volte questo comando non è riuscito con questa uscita: mysqld dead but subsys locked. In questi casi, l'unica cosa a cui sono stato in grado di pensare di ripristinare la situazione è riavviare il server, dopo di che è possibile riavviare MySQL. In questi casi, l'output è simile al seguente:

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)

Ecco cosa free -memette attualmente il comando :

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

Di solito la colonna "libera" è compresa tra 50 e 100 MB.

L'output del comando 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

Non ho modificato alcuna impostazione o file di codice di Moodle, tranne /var/www/html/moodle/config.php, che assomiglia a questo (righe di commento eliminate per risparmiare spazio):

<?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

(Tuttavia, ho installato due plugin Moodle, il modulo Presence e il blocco , ma non vedo come potrebbero essere coinvolti con questo problema.)

Anche dopo essermi aggiornato /etc/my.cnfal suo stato attuale una settimana fa, MySQL si è schiantato un paio di volte con i sintomi indicati sopra. Essendo un principiante nell'amministrazione del database e dopo aver fatto molti google su questo problema, sono in perdita su cosa fare dopo. Eventuali suggerimenti? Devo pubblicare più dati di configurazione?

Aggiunta alla modifica:

I contenuti del file /var/log/messages.1sono:

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).

e quindi le linee relative al riavvio alle 11:42.

Aggiunta alla modifica n. 2:

Ho provato a commentare la risposta di Michael, ma mi sono imbattuto nel limite di commenti dei personaggi, quindi sto rispondendo qui.

Grazie per la tua risposta, Michael. Ho appena modificato la mia domanda per includere il contenuto del registro di sistema della macchina al momento del crash. (CentOS sembra chiamare il suo registro di sistema /var/log/messages.)

Sì, sia MySQL che i log di sistema sembrano quasi identici a quelli della domanda a cui ti sei collegato. E ora che lo dici, è abbastanza ovvio che il mysql restartedmessaggio significa che MySQL si è già bloccato. Il registro di sistema indica che è oom_killerciò che ha ottenuto il processo. Nella tua risposta precedente, scrivi: "Prima ipotesi: i processi figlio di Apache funzionano in modo anomalo". Mi sembra che anche Apache sia l'ovvio sospetto qui.

In precedenza, ho trovato l'articolo Ottimizzazione di MySQL e Apache per l'utilizzo di memoria insufficiente, parte 1 . Per configurare Apache, l'autore consiglia: "Prima di tutto, Apache. La mia prima affermazione è, se puoi evitarlo, provaci. Lighttpd e thttpd sono entrambi ottimi server web senza fronzoli, e puoi eseguire lighttpd con PHP. Anche se tu stai gestendo un sito ad alto volume, puoi ottenere seriamente delle prestazioni passando contenuto statico (immagini e file javascript, di solito) a un server HTTPd leggero e superveloce come Lighttpd. "

Sto pensando di seguire il consiglio dell'autore e ho concordato con il mio cliente che il prossimo fine settimana sostituirò Apache con Lighttpd sul server. Spero che risolva i problemi. Probabilmente non è possibile utilizzare due server virtuali.

Non avevo pensato che usare due server open source stabili e maturi come MySQL e Apache sulla stessa macchina, con una ragionevole quantità di memoria, sarebbe stato così problematico.

Risposte:


36

Si prega di rivedere la mia risposta a questa recente domanda . Credo che le circostanze siano identiche.

Non modificare la configurazione di MySQL a questo punto, poiché MySQL non è il problema, è solo un sintomo del problema ... che sembra che tu abbia un sistema con una piccola quantità di memoria e zero spazio di swap.

Il tuo server non si arresta in modo anomalo "perché" la memoria non può essere allocata per il pool di buffer. Il tuo server si arresta in modo anomalo ... e quindi non è in grado di riavviarsi successivamente a causa dell'indisponibilità della memoria di sistema. Tutta la memoria configurata per il pool di buffer InnoDB viene richiesta dal sistema all'avvio di mysql.

Quando viene visualizzato questo messaggio di registro ...

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

... il tuo server è già morto. Se non ha registrato nulla prima di questo, non registrerà nulla sul primo arresto anomalo. I registri successivi provengono da dopo il tentativo automatico di riavvio.

Controlla il tuo syslog e dovresti trovare i messaggi in cui il kernel è andato alla ricerca di processi da eliminare a causa di una condizione di memoria insufficiente.

Il passaggio 1 sarebbe probabilmente quello di aggiungere spazio di swap e / o allocare RAM, se possibile.

Se ciò non è possibile, potresti effettivamente considerare di ridurre la dimensione del pool di buffer innodb nella configurazione. (Non avrei mai pensato di sentirmi dire davvero). Finché il tuo database è piccolo e il tuo traffico è leggero, potresti non aver bisogno di un pool di buffer così grande ... e poiché la memoria del pool di buffer InnoDB è tutta allocata all'avvio, sia che sia necessaria o meno, ciò libererebbe parte del tuo memoria di sistema per qualsiasi altra cosa lo richieda. (La raccomandazione dal 75% all'80% di RAM totale per il dimensionamento del pool di buffer è vera solo se l'intero server è dedicato a MySQL.)

Il passaggio 2 sarà quello di rivedere il modello di fork di Apache e cosa potrebbe essere necessario fare diversamente nella configurazione per evitare che sovraccarichi il server. È abbastanza probabile che una crescita incontrollata della quantità o della memoria dei processi figlio di Apache stia dando inizio a una serie di eventi, portando il kernel a uccidere MySQL per cercare di evitare un arresto completo dell'intero server.

A seconda di quanta flessibilità hai, potresti anche considerare due macchine virtuali separate per Apache e MySQL.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.