Cloud SQL untuk MySQL dari Google Cloud adalah layanan database yang terkelola sepenuhnya untuk membantu Anda menyiapkan, memelihara, mengelola, dan mengatur database MySQL, PostgreSQL, atau SQL Server di Google Cloud Platform. Cloud SQL menjalankan banyak database MySQL dalam fleet-nya dan melihat beberapa instance MySQL menggunakan memori tinggi dan error karena error kehabisan memori (OOM) merupakan hal yang biasa. Artikel ini akan membantu Anda memecahkan masalah memori MySQL.
Kondisi kehabisan memori (OOM) terjadi saat proses mencoba mengalokasikan memori dan gagal karena server tidak memiliki memori yang tersedia. Hal ini sering kali mengakibatkan Linux OOM Killer, yakni proses yang digunakan kernel Linux ketika sistem hampir kehabisan memori, sehingga menghentikan proses database.
Error database karena kondisi OOM tidak ideal karena proses database dihentikan menggunakan perintah SIGKILL yang membuat aplikasi tidak memiliki peluang untuk melakukan penonaktifan MySQL secara normal. Hal ini menyebabkan masalah berikut:
MySQL menambahkan instrumentasi memori di performance_schema mulai dari versi 5.7 yang membantu memahami alokasi memori MySQL. Artikel ini akan membantu Anda memecahkan masalah memori MySQL menggunakan performance_schema.
Setiap instance Cloud SQL didukung oleh mesin virtual (VM) yang berjalan di server Google Cloud host. Setiap VM mengoperasikan program database, seperti Server MySQL dan agen layanan yang menyediakan layanan pendukung, seperti logging dan pemantauan. Cloud SQL mencadangkan sebagian memori untuk sistem operasi (OS), agen layanan, dan mengalokasikan memori yang tersisa untuk program database seperti mysqld.
Tabel berikut menunjukkan alokasi memori untuk proses mysqld dan konfigurasi kumpulan buffer InnoDB default untuk setiap jenis mesin.
Jenis mesin | RAM Instance dalam GIB (Byte) | Memori mysqld (GB) | Kumpulan Buffer InnoDB dalam GiB (Byte) | Kumpulan Buffer (% dari RAM Instance) | Kumpulan Buffer (% dari memori mysqld) |
db-g1-small | 1.7(1825361101) | 1,11 | 0.625(671088640) | 37% | 56% |
db-custom-1-3840 | 3.75(4026531840) | 2,97 | 1.375(1476395008) | 37% | 46% |
db-custom-2-7680 | 7.5(8053063680) | 6.72 | 4(4294967296) | 53% | 60% |
db-custom-2-13312 | 13(13958643712) | 12 | 9(9663676416) | 69% | 75% |
db-custom-4-15360 | 15(16106127360) | 14 | 10.5(11274289152) | 70% | 76% |
db-custom-4-26624 | 26(27917287424) | 24 | 19(20401094656) | 73% | 79% |
db-custom-8-30720 | 30(32212254720) | 28 | 22(23622320128) | 73% | 80% |
db-custom-8-53248 | 52(55834574848) | 48 | 38(40802189312) | 73% | 79% |
db-custom-16-61440 | 60(64424509440) | 55 | 44(47244640256) | 73% | 80% |
db-custom-16-106496 | 104(111669149696) | 96 | 75(80530636800) | 72% | 78% |
db-custom-32-122880 | 120(128849018880) | 110 | 87(93415538688) | 73% | 79% |
db-custom-32-212992 | 208(223338299392) | 191 | 150(161061273600) | 72% | 78% |
db-custom-64-245760 | 240(257698037760) | 221 | 173(185757335552) | 72% | 78% |
db-custom-96-368640 | 360(386547056640) | 331 | 260(279172874240) | 72% | 79% |
db-custom-64-425984 | 416(446676598784) | 383 | 300(322122547200) | 72% | 78% |
db-custom-96-638976 | 624(670014898176) | 574 | 450(483183820800) | 72% | 78% |
Jenis mesin
RAM Instance dalam GIB (Byte)
Memori mysqld (GB)
Kumpulan Buffer InnoDB dalam GiB (Byte)
Kumpulan Buffer (% dari RAM Instance)
Kumpulan Buffer (% dari memori mysqld)
db-g1-small
1.7(1825361101)
1,11
0.625(671088640)
37%
56%
db-custom-1-3840
3.75(4026531840)
2,97
1.375(1476395008)
37%
46%
db-custom-2-7680
7.5(8053063680)
6.72
4(4294967296)
53%
60%
db-custom-2-13312
13(13958643712)
12
9(9663676416)
69%
75%
db-custom-4-15360
15(16106127360)
14
10.5(11274289152)
70%
76%
db-custom-4-26624
26(27917287424)
24
19(20401094656)
73%
79%
db-custom-8-30720
30(32212254720)
28
22(23622320128)
73%
80%
db-custom-8-53248
52(55834574848)
48
38(40802189312)
73%
79%
db-custom-16-61440
60(64424509440)
55
44(47244640256)
73%
80%
db-custom-16-106496
104(111669149696)
96
75(80530636800)
72%
78%
db-custom-32-122880
120(128849018880)
110
87(93415538688)
73%
79%
db-custom-32-212992
208(223338299392)
191
150(161061273600)
72%
78%
db-custom-64-245760
240(257698037760)
221
173(185757335552)
72%
78%
db-custom-96-368640
360(386547056640)
331
260(279172874240)
72%
79%
db-custom-64-425984
416(446676598784)
383
300(322122547200)
72%
78%
db-custom-96-638976
624(670014898176)
574
450(483183820800)
72%
78%
Untuk instance yang memiliki RAM 10 GB ke atas, proses mysqld dibatasi untuk menggunakan 92% RAM instance dan kumpulan buffer InnoDB dikonfigurasi dalam kisaran 75-80% dari memori yang tersedia untuk proses mysqld. Selain kumpulan buffer InnoDB, MySQL mengalokasikan beberapa buffer dan cache untuk meningkatkan performa. Lihat artikel ini untuk memahami alokasi memori di MySQL.
Ketika penggunaan memori mysqld tumbuh melampaui batas proses mysqld yang dikonfigurasi, killer OOM Linux akan menghentikan proses mysqld karena merupakan konsumen memori terbesar pada instance.
performance_schema adalah fitur MySQL untuk memantau eksekusi server di tingkat bawah. Cloud SQL untuk MySQL memungkinkan pengaktifan performance_schema pada instance yang memiliki ukuran RAM 3 GB atau lebih. Fitur ini diaktifkan secara default pada instance dengan RAM minimal 15 GB, dimulai pada versi MySQL 8.0.
Performance_schema dinonaktifkan secara default untuk versi MySQL 5.6 dan 5.7. Fitur ini dapat diaktifkan menggunakan flag database.
Mengaktifkan performance_schema melibatkan beberapa overhead performa dan juga memiliki implikasi memori. Lihat Model Alokasi Memori Skema Performa untuk memahami alokasi memorinya.
Instrumentasi memori performance_schema membantu memantau penggunaan memori di MySQL. Instrumen memori memiliki nama dalam bentuk memory/code_area/instrument_name dengan code_area berupa nilai seperti sql atau Innodb dan instrument_name adalah detail instrumen.
MySQL 5.7 mengaktifkan beberapa instrumen memori secara default. Anda dapat mengaktifkannya dengan memperbarui kolom ENABLED pada tabel performance_schema.setup_instruments.
mysql> memilih version();
+-------------------+
| version() |
+-------------------+
| 5.7.39-google-log |
+-------------------+
1 baris dalam set (0,00 detik)
mysql> SELECT enabled, count(*) FROM performance_schema.setup_instruments WHERE NAME LIKE '%memory%' group by enabled;
+---------+----------+
| enabled | count(*) |
+---------+----------+
| YES | 70 |
| NO | 306 |
+---------+----------+
2 baris dalam set (0,00 detik)
mysql> UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'memory/%';
Kueri OK, 306 baris terdampak (0,00 detik)
Baris yang cocok: 376 Diubah: 306 Peringatan: 0
mysql> SELECT enabled, count(*) FROM performance_schema.setup_instruments WHERE NAME LIKE '%memory%' group by enabled;
+---------+----------+
| enabled | count(*) |
+---------+----------+
| YES | 376 |
+---------+----------+
1 baris dalam set (0,00 detik)
Mengaktifkan instrumen memori pada runtime hanya akan menghitung objek memori yang dibuat setelah mengaktifkan instrumentasi. Oleh karena itu, sebaiknya tunggu server mengumpulkan data yang cukup untuk tujuan pemecahan masalah.
MySQL 8.0 mengaktifkan semua instrumen memori secara default.
mysql> memilih version();
+---------------+
| version() |
+---------------+
| 8.0.28-google |
+---------------+
1 baris dalam set (0,00 detik)
mysql> SELECT enabled, count(*) FROM performance_schema.setup_instruments WHERE NAME LIKE '%memory%' group by enabled;
+---------+----------+
| enabled | count(*) |
+---------+----------+
| YES | 490 |
+---------+----------+
1 baris dalam set (0,00 detik)
Skema sys berisi banyak tampilan yang merangkum data performance_schema ke dalam bentuk yang mudah dipahami. Sebagian besar tampilan ini muncul berpasangan. Keduanya memiliki nama yang sama dan salah satunya memiliki awalan x$. Tampilan berikut ini tersedia di MySQL 5.7 dan 8.0 untuk menampilkan alokasi memori pada level yang berbeda.
mysql> menggunakan sys;
Database diubah
mysql> menampilkan tabel seperti '%memory%';
+-------------------------------------+
| Tables_in_sys (%memory%) |
+-------------------------------------+
| memory_by_host_by_current_bytes |
| memory_by_thread_by_current_bytes |
| memory_by_user_by_current_bytes |
| memory_global_by_current_bytes |
| memory_global_total |
| x$memory_by_host_by_current_bytes |
| x$memory_by_thread_by_current_bytes |
| x$memory_by_user_by_current_bytes |
| x$memory_global_by_current_bytes |
| x$memory_global_total |
+-------------------------------------+
10 baris dalam set (0,02 detik)
Tampilan sys.memory_global_total merangkum total penggunaan memori dalam format yang dapat dibaca.
mysql> memilih * dari sys.memory_global_total;
+-----------------+
| total_allocated |
+-----------------+
| 12.43 GiB |
+-----------------+
1 baris dalam set (0,44 detik)
sys.x$memory_global_total menampilkan informasi yang sama tetapi dalam byte.
mysql> memilih * dari sys.x$memory_global_total;
+-----------------+
| total_allocated |
+-----------------+
| 13351482992 |
+-----------------+
1 baris dalam set (1,39 detik)
Tampilan tanpa awalan x$ dimaksudkan untuk memberikan output yang lebih ramah pengguna dan lebih mudah dibaca. Tampilan dengan awalan x$ yang menampilkan nilai yang sama dalam bentuk mentah lebih ditujukan untuk digunakan dengan alat lain yang melakukan pemrosesannya sendiri pada data.
Tampilan sys.memory_global_by_current_bytes menampilkan penggunaan memori saat ini yang dikelompokkan menurut jenis alokasi (event_name) misalnya memory/innodb/buf_buf_pool (kumpulan buffer InnoDB). Secara default, baris diurutkan berdasarkan jumlah memori yang digunakan secara menurun.
Sebelum kita melihat perincian setiap jenis alokasi, ada baiknya Anda memiliki ringkasan penggunaan memori untuk setiap area kode seperti Innodb, sql, performance_schema, dan banyak lagi.
Kueri berikut menggabungkan memori yang saat ini dialokasikan berdasarkan area kode.
SELECT SUBSTRING_INDEX(event_name,'/',2) AS code_area,
FORMAT_BYTES(SUM(current_alloc)) AS current_alloc
FROM sys.x$memory_global_by_current_bytes
GROUP BY SUBSTRING_INDEX(event_name,'/',2)
ORDER BY SUM(current_alloc) DESC;
+---------------------------+---------------+
| code_area | current_alloc |
+---------------------------+---------------+
| memory/innodb | 11.28 GiB |
| memory/performance_schema | 520.02 MiB |
| memory/temptable | 514.00 MiB |
| memory/sql | 106.12 MiB |
| memory/mysys | 43.25 MiB |
| memory/vio | 372.15 KiB |
| memory/myisam | 696 bytes |
| memory/csv | 88 bytes |
| memory/blackhole | 88 bytes |
+---------------------------+---------------+
9 baris dalam set (1,02 detik)
Output ini menunjukkan bahwa innodb adalah konsumen memori terbesar yang diikuti oleh performance_schema dan tabel sementara.
Sekarang, kueri sys.memory_global_by_current_bytes secara langsung menunjukkan penggunaan memori untuk struktur internal MySQL seperti yang dijelaskan di kolom event_name. Jika Anda memecahkan masalah peningkatan memori yang tidak normal, Anda dapat mengidentifikasi sumber dengan melihat output tampilan ini.
mysql> pilih event_name,current_alloc,high_alloc, dari sys.memory_global_by_current_bytes limit 5;
+-------------------------------+---------------+------------+
| event_name | current_alloc | high_alloc |
+-------------------------------+---------------+------------+
| memory/innodb/buf_buf_pool | 10.72 GiB | 10.72 GiB |
| memory/temptable/physical_ram | 514.00 MiB | 515.00 MiB |
| memory/innodb/hash0hash | 292.69 MiB | 292.69 MiB |
| memory/innodb/memory | 191.77 MiB | 197.94 MiB |
| memory/sql/TABLE | 60.39 MiB | 62.35 MiB |
+-------------------------------+---------------+------------+
5 baris dalam set (0,45 detik)
Berikut detail setiap jenis alokasi.
Jenis Alokasi | Detail |
memory/innodb/buf_buf_pool | Memori yang digunakan oleh Kumpulan Buffer InnoDB |
memory/temptable/physical_ram | Memori yang digunakan oleh tabel internal sementara |
memory/innodb/hash0hash | Memori yang digunakan oleh tabel hash InnoDB |
memory/innodb/memory | Memori yang digunakan oleh berbagai buffer InnoDB |
memory/sql/TABLE | Memori yang digunakan oleh objek TABLE dan root mem-nya |
Jenis Alokasi
Detail
memory/innodb/buf_buf_pool
Memori yang digunakan oleh Kumpulan Buffer InnoDB
memory/temptable/physical_ram
Memori yang digunakan oleh tabel internal sementara
memory/innodb/hash0hash
Memori yang digunakan oleh tabel hash InnoDB
memory/innodb/memory
Memori yang digunakan oleh berbagai buffer InnoDB
memory/sql/TABLE
Memori yang digunakan oleh objek TABLE dan root mem-nya
Tampilan ini merangkum penggunaan memori yang dikelompokkan oleh pengguna. Jika pengguna memiliki beberapa koneksi, tampilan ini akan menjumlahkan penggunaan memori untuk semua instance pengguna.
mysql> memilih user,current_allocations dari memory_by_user_by_current_bytes;
+-----------------+-------------------+
| user | current_allocated |
+-----------------+-------------------+
| sbtest | 60.30 MiB |
| background | 2.68 MiB |
| root | 1.52 MiB |
| event_scheduler | 16.38 KiB |
+-----------------+-------------------+
4 baris dalam set (1,16 detik)
Jika Anda menggunakan pengguna yang berbeda untuk setiap aplikasi/tugas (disarankan), tampilan ini dapat membantu mengidentifikasi apakah aplikasi atau tugas tertentu menggunakan memori tinggi.
Tampilan ini merangkum penggunaan memori yang dikelompokkan menurut nama host.
mysql> memilih host,current_allocations dari memory_by_host_by_current_bytes;
+------------+-------------------+
| host | current_allocated |
+------------+-------------------+
| 10.128.0.8 | 62.10 MiB |
| background | 2.70 MiB |
| 127.0.0.1 | 311.01 KiB |
| localhost | 16.38 KiB |
+------------+-------------------+
4 baris dalam set (1,58 detik)
Tampilan ini berguna untuk mengidentifikasi penggunaan memori per host klien. Memiliki beberapa server klien/aplikasi sangat umum saat ini. Tampilan ini akan membantu mengidentifikasi apakah ada klien atau beban kerja tertentu yang menyebabkan penggunaan memori yang tinggi. Anda juga dapat men-deploy perubahan pada satu server klien/aplikasi terlebih dahulu, memantau dampaknya pada memori (dengan membandingkan penggunaan memori dengan host klien lainnya), dan membuat keputusan yang tepat.
Tampilan ini merangkum penggunaan memori, yang dikelompokkan menurut thread, dan membantu menemukan thread yang menggunakan sebagian besar memori.
mysql> memilih thread_id,user,current_allocations dari sys.memory_by_thread_by_current_bytes limit 5;
+-----------+-------------------+-------------------+
| thread_id | user | current_allocated |
+-----------+-------------------+-------------------+
| 12999 | sbtest@10.128.0.8 | 3.80 MiB |
| 12888 | sbtest@10.128.0.8 | 3.75 MiB |
| 12760 | sbtest@10.128.0.8 | 3.68 MiB |
| 13128 | sbtest@10.128.0.8 | 3.67 MiB |
| 13221 | sbtest@10.128.0.8 | 3.47 MiB |
+-----------+-------------------+-------------------+
5 baris dalam set (2,29 detik)
Jika Anda menemukan thread tertentu yang menggunakan memori tinggi, Anda dapat memfilter log kueri MySQL yang lambat atau log umum menggunakan thread_id dan mengidentifikasi sesi/kueri yang menyebabkan pertumbuhan memori.
Memecahkan masalah penggunaan memori yang tinggi adalah tugas yang menantang. Untungnya, instrumentasi memori performance_schema membantu pengguna memahami bagaimana memori digunakan oleh struktur MySQL internal. Tampilan skema sistem memudahkan penafsiran informasi. Jika Anda mengalami masalah terkait memori, fitur ini akan membantu Anda menemukan sumber masalah dan Anda dapat memperbaiki masalah yang sama dengan mengubah konfigurasi/kueri.
Contoh:
Jika Anda mengalami situasi di mana instance MySQL menggunakan memori lebih tinggi dari seharusnya dan penggunaan memori terus meningkat hingga server kehabisan memori, dan performance_schema menunjukkan kesenjangan dalam memori total versus memori yang diinstrumentasi atau tidak menunjukkan ke mana perginya memori, mungkin itu adalah gejala kebocoran memori. Jika Anda mencurigai adanya kebocoran memori, Anda dapat melakukan langkah-langkah berikut:
Mulailah membangun solusi di Google Cloud dengan kredit gratis senilai $300 dan lebih dari 20 produk yang selalu gratis.