MySQL terputus-putus mengalami kesalahan "Kesalahan fatal: tidak dapat mengalokasikan memori untuk buffer pool"

40

Ditambahkan pada edit, 2013-05-29: Karena ini adalah pertanyaan dan diskusi yang panjang, inilah ringkasan singkat dari pertanyaan dan solusinya. Saya punya masalah menjalankan MySQL dan Apache pada server Linux kecil (memori 1 GB). Apache terus menuntut lebih banyak memori, dan sebagai konsekuensinya, OS selalu membunuh MySQL untuk mendapatkan kembali ingatannya. Solusinya adalah mengganti Apache dengan Lighttpd. Setelah saya melakukan itu, penggunaan memori pada server telah benar-benar stabil selama beberapa bulan sekarang, dan saya tidak pernah mengalami crash apa pun. akhir pengeditan

Saya seorang administrator sistem pemula untuk server virtual kecil. Fungsi utama server adalah menjalankan perangkat lunak sistem manajemen kursus Moodle sumber terbuka , yang ditulis dalam PHP. Itu bergantung pada database, dalam hal ini MySQL, dan server web, dalam hal ini Apache.

Server menjalankan rilis 64-bit CentOS 5.8 (Final) dengan 1 GB memori dan 200 GB disk, versi kernel 2.6.18-308.8.2.el5xen. Versi MySQL adalah Ver 14.14 Distrib 5.5.25, untuk Linux (x86_64) menggunakan readline 5.1.

Saya tidak berpikir perangkat lunak Moodle adalah pengguna MySQL yang banyak. Saat ini, hanya sekitar sepuluh guru yang memiliki akses ke sana, dan ketika saya dump dan kompres dengan bzip2 seluruh database, ukuran dump yang dihasilkan kurang dari 1 MB.

Saya mengatur sistem beberapa bulan yang lalu. Server Apache telah stabil selama ini, tetapi MySQL telah mogok beberapa kali. Saya sudah mencoba belajar tentang konfigurasi optimal dari web, dan terakhir kali saya mengubah /etc/my.cnffile, saya menggunakan file /usr/share/doc/mysql55-server-5.5.25/my-large.cnfyang disertakan dengan MySQL sebagai contoh. File mengatakan bahwa itu dimaksudkan untuk sistem dengan memori 512 MB, jadi saya pikir menggunakan parameter konfigurasi yang terkait dengan memori akan aman untuk sistem ini. (Saya sebelumnya mengkonfigurasi parameter terkait memori MySQL dengan angka yang jauh lebih kecil, dan saya pikir itu mungkin menyebabkan crash. Sementara crash masih terjadi, sistem setidaknya sekarang lebih cepat.) Ini adalah isi saat ini dari /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

Seperti yang Anda lihat dalam konfigurasi, pengaturan menggunakan mesin InnoDB, dan hanya melayani permintaan dari localhost. Terlepas dari administrator sistem (saya), Moodle adalah satu-satunya pengguna MySQL.

Ketika MySQL macet, berikut ini selalu ditulis ke file log /var/log/mysqld.log(kecuali untuk cap waktu, tentu saja):

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

Kadang-kadang saya bisa restart MySQL dengan memerintahkan service mysqld restart, tapi kadang-kadang bahwa perintah gagal dengan output ini: mysqld dead but subsys locked. Dalam kasus ini, satu-satunya hal yang dapat saya pikirkan untuk memulihkan situasi adalah me-restart server, setelah itu MySQL dapat di-restart. Dalam kasus ini, outputnya terlihat seperti ini:

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)

Inilah yang free -msaat ini dihasilkan oleh perintah :

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

Biasanya kolom "gratis" adalah antara 50 dan 100 MB.

Output dari perintah 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

Saya belum mengubah pengaturan atau file kode Moodle apa pun, kecuali untuk /var/www/html/moodle/config.php, yang terlihat seperti ini (baris komentar dihapus untuk menghemat ruang):

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

(Namun, saya telah menginstal dua plugin Moodle, modul Kehadiran dan blokir , tetapi saya tidak melihat bagaimana mereka bisa terlibat dengan masalah ini.)

Bahkan setelah saya memperbarui /etc/my.cnfke kondisi saat ini seminggu yang lalu, MySQL telah mengalami crash beberapa kali dengan gejala yang diberikan di atas. Menjadi pemula dalam administrasi basis data, dan setelah melakukan banyak googling tentang masalah ini, saya bingung apa yang harus dilakukan selanjutnya. Ada saran? Haruskah saya memposting lebih banyak data konfigurasi?

Tambahan pada edit:

Isi file /var/log/messages.1adalah:

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

dan kemudian baris terkait dengan reboot pada 11:42.

Tambahan pada edit # 2:

Saya mencoba mengomentari jawaban Michael, tetapi saya melanggar batas karakter komentar, jadi saya menjawab di sini.

Terima kasih atas jawaban Anda, Michael. Saya baru saja mengedit pertanyaan saya untuk memasukkan isi log sistem mesin pada saat crash. (CentOS tampaknya memanggil log sistemnya /var/log/messages.)

Ya, baik log MySQL dan sistem tampak hampir identik dengan yang ada di pertanyaan yang Anda tautkan. Dan sekarang setelah Anda menyebutkannya, agak jelas bahwa mysql restartedpesan tersebut berarti bahwa MySQL sudah mogok. Log sistem menunjukkan bahwa itulah oom_killeryang mendapatkan prosesnya. Dalam jawaban Anda sebelumnya, Anda menulis: "Tebakan pertama: proses anak apache menjalankan amuk." Menurut saya, Apache adalah tersangka yang jelas di sini juga.

Sebelumnya, saya menemukan artikel Mengoptimalkan MySQL dan Apache untuk Penggunaan Memori Rendah, Bagian 1 . Untuk mengkonfigurasi Apache, penulis merekomendasikan: "Pertama, Apache. Pernyataan pertama saya adalah, jika Anda dapat menghindarinya, cobalah. Lighttpd dan thttpd keduanya sangat bagus tanpa embel-embel webservers, dan Anda dapat menjalankan lighttpd dengan PHP. Bahkan jika Anda Sedang menjalankan situs volume tinggi, Anda dapat secara serius mendapatkan kinerja dengan mengirimkan konten statis (gambar dan file javascript, biasanya) ke server HTTPd ringan dan super cepat seperti Lighttpd. "

Saya berpikir untuk mengambil saran penulis, dan telah setuju dengan klien saya bahwa akhir pekan depan, saya akan mengganti Apache dengan Lighttpd di server. Saya harap itu akan menyelesaikan masalah. Menggunakan dua server virtual kemungkinan besar tidak mungkin.

Saya tidak berpikir bahwa menggunakan dua server open-source yang stabil dan matang seperti MySQL dan Apache pada mesin yang sama, dengan jumlah memori yang masuk akal, akan menyusahkan ini.

Teemu Leisti
sumber

Jawaban:

36

Harap tinjau jawaban saya untuk pertanyaan terakhir ini . Saya percaya situasinya identik.

Jangan mengubah konfigurasi MySQL Anda pada saat ini, karena MySQL bukan masalahnya - itu hanya gejala dari masalah ... yaitu Anda memiliki sistem dengan jumlah memori yang kecil dan ruang swap nol.

Server Anda tidak menabrak "karena" memori tidak dapat dialokasikan untuk kumpulan buffer. Server Anda macet ... dan kemudian tidak dapat memulai ulang karena tidak tersedianya memori sistem. Semua memori yang dikonfigurasikan untuk kumpulan buffer InnoDB diminta dari sistem saat startup mysql.

Ketika Anda melihat pesan log ini ...

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

... server Anda sudah mati. Jika belum mencatat apa pun sebelum ini, itu tidak akan mencatat apa pun tentang kerusakan pertama. Log berikutnya berasal dari setelah upaya otomatis untuk me-restart.

Periksa syslog Anda dan Anda akan menemukan pesan di mana kernel mencari proses untuk membunuh karena kondisi kehabisan memori yang ekstrem.

Langkah 1 mungkin akan menambahkan beberapa ruang swap dan / atau mengalokasikan RAM jika memungkinkan.

Jika itu tidak memungkinkan, Anda mungkin benar-benar mempertimbangkan untuk mengurangi ukuran innodb-buffer-pool dalam konfigurasi Anda. (Saya tidak pernah berpikir saya benar-benar mendengar diri saya mengatakan itu). Selama database Anda kecil dan traffic Anda ringan, Anda mungkin tidak memerlukan buffer pool yang besar ... dan karena memori InnoDB Buffer Pool semuanya dialokasikan pada startup apakah diperlukan atau tidak, ini akan membebaskan sebagian dari Anda memori sistem untuk apa pun yang menuntutnya. (Rekomendasi 75% hingga 80% dari total RAM untuk ukuran buffer pool hanya benar jika seluruh server didedikasikan untuk MySQL.)

Langkah 2 adalah meninjau model forking Apache dan apa yang mungkin perlu Anda lakukan secara berbeda dalam konfigurasi untuk mencegahnya membanjiri server Anda. Sangat mungkin bahwa pertumbuhan yang tidak terkendali dalam jumlah atau persyaratan memori proses anak Apache memulai serangkaian peristiwa, yang mengakibatkan kernel membunuh MySQL untuk mencoba menghindari kehancuran total seluruh server.

Tergantung pada seberapa banyak fleksibilitas yang Anda miliki, Anda bahkan dapat mempertimbangkan dua mesin virtual terpisah untuk Apache dan MySQL.

Michael - sqlbot
sumber