MySQL tidak melepaskan memori

8

MySQL sepertinya ingin menyimpan seluruh tabel dalam cache (ukuran tabel = ~ 20GB) setelah memasukkan besar atau pernyataan pilih dilakukan di atasnya. Sekarang pool buffer innodb saya adalah 20GB. Total RAM adalah 32GB. Saya akan memberikan beberapa penggunaan memori dan output dari status innodb serta output dari mysqltuner. Sudah membuatku gila selama beberapa hari terakhir. Tolong bantu! Saya menghargai umpan balik dan tolong beri tahu saya jika Anda memerlukan informasi lebih lanjut.

Juga, melakukan 'FLUSH TABLES' hanya menutup dan membukanya kembali dalam memori. Setidaknya saya pikir itulah yang terjadi. Inilah status memori innodb saat ini sebelum saya melakukan banyak sisipan:

----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 21978152960; in additional pool allocated 0
Dictionary memory allocated 6006471
Buffer pool size   1310719
Free buffers       347984
Database pages     936740
Old database pages 345808
Modified db pages  0
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 78031, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 551887, created 384853, written 4733512
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool page gets since the last printout
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 936740, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]

penggunaan memori mysqld persen: 60,9%

penggunaan memori mysqld persen setelah sisipan (catatan 1 mil): 63,3%

dan kemudian setelah lebih banyak sisipan (catatan 3 mil): 70,2%

bukankah seharusnya habis sekitar 62,5% ? (20 / 32GB) total ram?

output dari pengurutan atas penggunaan MEM saya:

top - 14:30:56 up 23:25,  3 users,  load average: 3.63, 2.31, 1.91
Tasks: 208 total,   4 running, 204 sleeping,   0 stopped,   0 zombie
Cpu(s): 96.0%us,  3.0%sy,  0.0%ni,  0.0%id,  1.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  28821396k total, 28609868k used,   211528k free,   138696k buffers
Swap: 33554428k total,    30256k used, 33524172k free,  1208184k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 1228 mysql     20   0 25.1g  19g 5512 S   31 70.2  62:01.10 mysqld

inilah output memori innodb setelah sisipan ini dilakukan:

----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 21978152960; in additional pool allocated 0
Dictionary memory allocated 6006471
Buffer pool size   1310719
Free buffers       271419
Database pages     1011886
Old database pages 373510
Modified db pages  4262
Pending reads 1
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 82521, not young 0
7.08 youngs/s, 0.00 non-youngs/s
Pages read 585218, created 426667, written 5192189
24.08 reads/s, 53.08 creates/s, 1135.07 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 1011886, unzip_LRU len: 0
I/O sum[0]:cur[266], unzip sum[0]:cur[0]

Menurut status innodb, total memori yang dialokasikan adalah sama - namun OS saya (Virtual Ubuntu Server 12.04) melaporkan lebih banyak penggunaan memori daripada itu. Penggunaan memori tetap sama dan di sini saya mendefinisikannya sebagai layanan MySQL tidak 'melepaskan' memori. Ada saran?

output dari mysqltuner.pl:

-------- Storage Engine Statistics -------------------------------------------
[--] Status: +ARCHIVE +BLACKHOLE +CSV -FEDERATED +InnoDB +MRG_MYISAM
[--] Data in MyISAM tables: 226M (Tables: 287)
[--] Data in InnoDB tables: 33G (Tables: 1000)
[--] Data in PERFORMANCE_SCHEMA tables: 0B (Tables: 17)
[--] Data in MEMORY tables: 0B (Tables: 1)
[!!] Total fragmented tables: 959

-------- Security Recommendations  -------------------------------------------
[OK] All database users have passwords assigned

-------- Performance Metrics -------------------------------------------------
[--] Up for: 23h 14m 27s (1M q [14.603 qps], 6K conn, TX: 16B, RX: 1B)
[--] Reads / Writes: 46% / 54%
[--] Total buffers: 22.2G global + 2.7M per thread (151 max threads)
[OK] Maximum possible memory usage: 22.6G (82% of installed RAM)
[OK] Slow queries: 0% (6/1M)
[OK] Highest usage of available connections: 6% (10/151)
[OK] Key buffer size / total MyISAM indexes: 2.0G/58.7M
[OK] Key buffer hit rate: 100.0% (216M cached / 38K reads)
[OK] Query cache efficiency: 81.2% (799K cached / 984K selects)
[!!] Query cache prunes per day: 5561
[OK] Sorts requiring temporary tables: 4% (819 temp sorts / 16K sorts)
[!!] Temporary tables created on disk: 27% (6K on disk / 22K total)
[OK] Thread cache hit rate: 99% (11 created / 6K connections)
[!!] Table cache hit rate: 0% (97 open / 10K opened)
[OK] Open file limit used: 12% (129/1K)
[OK] Table locks acquired immediately: 99% (433K immediate / 433K locks)
[!!] InnoDB  buffer pool / data size: 20.0G/33.6G
[OK] InnoDB log waits: 0
-------- Recommendations -----------------------------------------------------
General recommendations:
    Run OPTIMIZE TABLE to defragment tables for better performance
    MySQL started within last 24 hours - recommendations may be inaccurate
    Enable the slow query log to troubleshoot bad queries
    When making adjustments, make tmp_table_size/max_heap_table_size equal
    Reduce your SELECT DISTINCT queries without LIMIT clauses
    Increase table_cache gradually to avoid file descriptor limits
    Read this before increasing table_cache over 64: http://bit.ly/1mi7c4C
Variables to adjust:
    query_cache_size (> 128M)
    tmp_table_size (> 128M)
    max_heap_table_size (> 16M)
    table_cache (> 431)
    innodb_buffer_pool_size (>= 33G)
ceri
sumber

Jawaban:

8

Pertama-tama lihat Arsitektur InnoDB (milik Percona CTP Vadim Tkachenko)

Arsitektur InnoDB

InnoDB

Status Anda untuk Buffer Pool mengatakan

Buffer pool ukuran 1310719

Itu Ukuran Buffer Anda di Halaman. Setiap halaman 16K . Ternyata 20G - 16K.

Harap perhatikan hal-hal berikut: Anda mendorong data ke Pool Buffer InnoDB. Apa yang berubah ?

Buffer pool size   1310719 
Free buffers       271419 (It was 347984)
Database pages     1011886 (Is was 936740)
Old database pages 373510 (It was 345808)
Modified db pages  4262 (It was 0)

Juga, perhatikan perbedaan antara Ukuran Buffer Pool di Halaman.

1310719 (ukuran kolam penyangga) - 1011886 (halaman Database) = 298833

Itu 29.833 halaman InnoDB. Berapa banyak ruang itu ???

mysql> select FORMAT(((1310719  - 1011886) * 16384) / power(1024,3),3) SpaceUsed;
+-----------+
| SpaceUsed |
+-----------+
| 4.560     |
+-----------+

Itu 4,56GB. Ruang itu digunakan untuk Bagian Sisipkan Penyangga dari Baki Penyangga InnoDB (alias Ubah Penyangga) . Ini digunakan untuk mengurangi perubahan pada indeks nonunique ke dalam System Tablespace File (yang semuanya telah diketahui sebagai ibdata1).

Mesin Penyimpanan InnoDB mengelola internal Buffer Pool. Oleh karena itu, InnoDB tidak akan pernah melampaui 62,5% RAM. Terlebih lagi, RAM untuk Buffer Pool tidak pernah diberikan kembali.

DI MANA 70,2% RAM DATANG DARI ???

Lihat kembali output dari mysqltuner.plpada baris-baris ini

[OK] Maximum possible memory usage: 22.6G (82% of installed RAM)
Key buffer size / total MyISAM indexes: 2.0G/58.7M
[--] Total buffers: 22.2G global + 2.7M per thread (151 max threads)

mysqld memiliki tiga cara utama mengalokasikan RAM

Setiap lonjakan kecil dalam Koneksi DB akan meningkatkan RAM melewati ambang 62,5% yang Anda lihat untuk InnoDB.

MyISAM (Catatan Samping)

Yang menarik perhatian saya adalah

Key buffer size / total MyISAM indexes: 2.0G/58.7M

Karena Anda memiliki indeks sangat sedikit untuk MyISAM. Anda dapat mengatur key_buffer_size ke 64M.

Anda tidak perlu me-restart mysql untuk itu. Lari saja

SET GLOBAL ket_buffer_size = 1024 * 1024 * 64;

Kemudian, modifikasi ini di my.cnf

[mysqld]
key_Buffer_size = 64M

Ini akan memberikan OS 2GB RAM. VM Anda hanya akan mencintaimu karenanya !!!

Cobalah !!!

CAVEAT

Berjalan FLUSH TABLESdi tabel InnoDB hanya menutup file terhadap .ibdfile. Ini tidak akan mendorong perubahan secara langsung. Perubahan harus dimigrasi melalui pipa InnoDB. Inilah sebabnya mengapa Anda melihat lonjakan Modified db pages. 4262 halaman yang diubah (66,59 MB) akan memerah ketika jadwal InnoDB memerahnya.

RolandoMySQLDBA
sumber
terima kasih banyak atas analisis mendalam. Itu jauh lebih masuk akal sekarang - jadi memang benar bahwa kolam buffer innodb akan tetap pada penggunaan memori maks dari waktu ke waktu (20GB)? Dan total memori yang akan digunakan mysqld adalah 82% ??
cherner
Itu adalah Ya untuk kedua pertanyaan
RolandoMySQLDBA
@RolandoMySQLDBA, Jika saya mengerti benar, MySQL tidak melepaskan memori dan ini adalah apa ini. Tidak?
Malus
1
@ MalalJan Jawaban saya bukan tentang memori yang dirilis. Jawaban saya membahas berapa banyak RAM yang digunakan untuk StorageEngines dan DB Connections. Terkadang, Koneksi DB yang tersisa tidak ditutup dengan benar dapat menahan RAM yang dialokasikan. Cache untuk buffer Engine Penyimpanan dapat diubah ukurannya secara dinamis untuk MyISAM (MySQL 5.x +) dan InnoDB (MySQL 5.7+). Cache untuk Koneksi DB dapat diubah ukurannya secara dinamis untuk koneksi masuk baru (bukan koneksi saat ini terbuka). Memori tidak dilepaskan karena bug kebocoran memori di mysqld.
RolandoMySQLDBA
@RolandoMySQLDBA. Di server kami memiliki lebih dari 10 database dan kami perlu membuat dump setiap hari dan masing-masing mysqldumpmengambil beberapa memori dan tidak melepaskannya. Jadi setelah semua dump kami memiliki sekitar 80% dari ram yang ditempati oleh proses mysql. Apakah Anda punya solusi untuk itu? Terima kasih
Malus
0

Saya menghadapi masalah serupa. Pertanyaan: apakah Anda menggunakan konfigurasi memori terpisah? (THP dan dibagi-pakai) Jika ya maka nonaktifkan hugepage dan biarkan MySQL yang menangani memori dan terus memonitornya. Juga periksa berapa banyak proses paralel yang berjalan di server termasuk proses dalam mode Tidur. Jika Anda menggunakan konfigurasi memori bersama maka Anda memerlukan lebih banyak memori untuk server ini.

Raja Naveed
sumber