Mengapa MySQL mengatakan saya kehabisan memori?

9

Saya mencoba menjalankan INSERT...SELECTMySQL yang cukup besar dengan JDBC, dan saya mendapat pengecualian berikut:

Exception in thread "main" java.sql.SQLException: Out of memory (Needed 1073741824 bytes)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)

Karena saya tidak benar-benar mengembalikan objek ResultSet, saya pikir ruang heap Java seharusnya tidak menjadi masalah. Namun, saya mencoba untuk meningkatkannya dan itu tidak baik. Saya kemudian mencoba menjalankan pernyataan di MySQL Workbench dan pada dasarnya saya mendapatkan hal yang sama:

Error Code 5: Out of memory (Needed 1073741816 bytes)

Saya seharusnya memiliki banyak RAM untuk menyelesaikan operasi ini (cukup untuk memenuhi seluruh tabel yang saya pilih), tetapi saya kira ada berbagai pengaturan yang perlu saya sesuaikan untuk memanfaatkan semua memori saya. Saya menjalankan Amazon EC2 High Memory Double Extra Large Instance dengan Windows Server 2008 AMI. Saya sudah mencoba mengutak-atik file my.ini untuk menggunakan pengaturan yang lebih baik, tetapi untuk semua yang saya tahu saya mungkin telah memperburuk keadaan. Berikut dump file itu:

[client]
port=3306
[mysql]
default-character-set=latin1
[mysqld]
port=3306
basedir="C:/Program Files/MySQL/MySQL Server 5.5/"
datadir="C:/ProgramData/MySQL/MySQL Server 5.5/Data/"
character-set-server=latin1
default-storage-engine=INNODB
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
max_connections=100
query_cache_size=1024M
table_cache=256
tmp_table_size=25G
thread_cache_size=8
myisam_max_sort_file_size=100G
myisam_repair_threads = 2
myisam_sort_buffer_size=10G
key_buffer_size=5000M
bulk_insert_buffer_size = 4000M
read_buffer_size=8000M
read_rnd_buffer_size=8000M
sort_buffer_size=1G
innodb_additional_mem_pool_size=26M
innodb_flush_log_at_trx_commit=2
innodb_log_buffer_size=13M
innodb_buffer_pool_size=23G
innodb_log_file_size=622M
innodb_thread_concurrency=18
innodb_file_per_table=TRUE
join_buffer_size=4G
max_heap_table_size = 10G

Jadi apakah ini hanya masalah mengubah pengaturan di atas agar berfungsi lebih baik untuk lingkungan saya? Jika demikian, pengaturan apa yang harus saya gunakan? Saya satu-satunya yang pernah menggunakan instance ini; Saya menggunakannya untuk proyek hobi pribadi saya yang melibatkan analisis statistik dataset besar. Karena itu, saya bebas untuk membiarkannya menghabiskan semua sumber daya yang tersedia untuk pertanyaan saya sendiri.

Jika ini bukan masalah mengubah pengaturan itu, apa masalahnya? Terima kasih atas bantuan yang dapat Anda tawarkan untuk cara mengkonfigurasi semuanya dengan lebih baik.

Michael McGowan
sumber
Siapa pun yang menggunakan cache permintaan 1g tidak memiliki petunjuk apa yang mereka lakukan.
@winmutt Anda mungkin benar, tetapi komentar Anda tidak membantu siapa pun tanpa penjelasan lebih lanjut. Bisakah Anda membantu kami dengan memberikan alasan sentimen Anda?
Michael McGowan
Alat praktis untuk memulai adalah tools.percona.com/wizard
KCD

Jawaban:

9

Mengingat ini adalah instalasi Windows, @DTest masih memberikan arahan awal yang tepat.

Terapkan rumus berikut:

Kebanyakan orang menggunakan ini:

Maximum MySQL Memory Usage = innodb_buffer_pool_size + key_buffer_size + (read_buffer_size + sort_buffer_size) X max_connections

Saya lebih memilih ini:

Maximum MySQL Memory Usage = innodb_buffer_pool_size + key_buffer_size + ((read_buffer_size + read_rnd_buffer_size + sort_buffer_size + join_buffer_size) X max_connections)

Variabel-variabel ini adalah yang perlu Anda sesuaikan sampai formula menghasilkan 80% dari RAM yang terpasang atau kurang.

sort_buffer_size
read_buffer_size
read_rnd_buffer_size
join_buffer_size
max_connections
RolandoMySQLDBA
sumber
4

Saya akan mencoba menurunkan ukuran buffer Anda. Membuatnya sebesar yang Anda miliki akan menimbulkan masalah. Berapa banyak memori yang Anda miliki untuk menjalankan nilai-nilai ini:

query_cache_size=1024M
myisam_max_sort_file_size=100G
myisam_sort_buffer_size=10G
key_buffer_size=5000M
bulk_insert_buffer_size = 4000M
read_buffer_size=8000M
read_rnd_buffer_size=8000M
sort_buffer_size=1G
innodb_buffer_pool_size=23G

Beberapa ukuran buffer dialokasikan per-utas, misalnya myisam_sort_buffer_size dari 10G mengalokasikan 10G untuk setiap utas.

Pertama-tama saya akan mengurangi nilai-nilai itu secara dramatis, dan kemudian menyelidiki nilai-nilai mana yang benar-benar Anda butuhkan untuk mengalokasikan RAM sebanyak ini (jika ada).

Derek Downey
sumber
4

Cara cepat untuk menentukan berapa banyak memori yang menurut MySQL dapat dialokasikan adalah sebagai berikut:

wget mysqltuner.pl

perl mysqltuner.pl

Ketika Anda menjalankan skrip ini, ia akan memberi tahu Anda berapa persen dari RAM yang diinstal yang menurut MySQL dapat dialokasikan dengan aman. Jika jawaban yang diberikan lebih dari 100%, Anda pasti perlu menurunkan ukuran buffer Anda. Yang utama untuk fokus adalah:

sort_buffer_size
read_buffer_size
read_rnd_buffer_size
join_buffer_size
max_connections
key_buffer_size (tidak terlalu efektif melewati 4G)

@Dest sudah menetapkan arah untuk Anda dalam jawabannya, jadi +1 untuk anwser-nya. Skrip perl akan memberi tahu Anda apa yang terjadi jika Anda tidak menyetelnya atau jika Anda mengubah nilai apa pun. Berikut ini sebuah contoh:

Seorang klien saya telah
read_buffer_size = 128K
read_rnd_buffer_size = 256K
sort_buffer_size = 2M
join_buffer_size = 128K
max_connections = 1050

Berikut ini adalah output dari mysqltuner.pl:

MySQLTuner 1.2.0 -
Laporan Bug Hayden Utama , permintaan fitur, dan unduhan di http://mysqltuner.com/
Jalankan dengan '--help' untuk opsi tambahan dan penyaringan keluaran.
Silakan masukkan login administratif MySQL Anda: lwdba
Silakan masukkan administrasi MySQL Anda kata sandi:

-------- Statistik Umum ---------------------------------------- ----------
[-] Pemeriksaan versi yang dilewati untuk skrip MySQLTuner
[OK] Saat ini menjalankan versi MySQL yang didukung 5.0.51a-community-log
[!!] Beralih ke OS 64-bit - MySQL saat ini tidak dapat menggunakan semua RAM Anda

-------- Statistik Mesin Penyimpanan --------------------------------------- ----
[-] Status: + Arsip -BDB + Federasi + InnoDB -ISAM -NDBCluster
[-] Data dalam tabel MyISAM: 319M (Tabel: 108)
[-] Data dalam tabel InnoDB: 2M (Tabel: 5)
[!!] Total tabel terfragmentasi: 22

-------- Metrik Kinerja ---------------------------------------- ---------
[-] Naik untuk: 52d 23j 15m 57d (72M q [15.875 qps], 241K conn, TX: 2B, RX: 1B)
[-] Baca / Menulis: 59% / 41%
[-] Total buffer: 34.0M global + 2.7M per utas (1050 maks utas)
[!!] Mengalokasikan> 2GB RAM pada sistem 32-bit dapat menyebabkan ketidakstabilan sistem
[!!] Penggunaan memori maksimum yang mungkin: 2.8G (72% RAM terpasang)
[OK] Permintaan lambat: 0% (54 / 72M)
[OK] Penggunaan tertinggi dari koneksi yang tersedia: 6% (65/1050)
[Oke] Ukuran buffer kunci / total indeks MyISAM: 8.0M / 82.1M
[OK] Tingkat hit buffer kunci: 100.0% (cache 4B / 1M berbunyi)
[!!] Cache permintaan dinonaktifkan
[OK] Urusan yang membutuhkan tabel sementara: 0% (0 temp sort / 948K macam)
[OK] Tabel sementara dibuat pada disk: 3% (total 11K pada disk / 380K)
[!!] Cache thread dinonaktifkan
[!!] Tingkat hit cache cache: 0% (64 dibuka / 32K dibuka)
[OK] Buka file batas yang digunakan: 2% (125 / 5K)
[OK] Kunci meja diperoleh segera: 99% (30M langsung / 30 kunci)
[OK] Ukuran data InnoDB / kumpulan buffer: 2,7M / 8,0M

-------- Rekomendasi ----------------------------------------- ------------
Rekomendasi umum:
Jalankan OPTIMIZE TABLE untuk mendefragmen tabel untuk kinerja yang lebih baik.
Aktifkan log kueri lambat untuk memecahkan masalah kueri buruk.
Setel thread_cache_size ke 4 sebagai nilai awal.
Menambah table_cache secara bertahap untuk menghindari batas deskriptor file
Variabel untuk menyesuaikan:
query_cache_size (> = 8M)
thread_cache_size (mulai dari 4)
table_cache (> 64)

Harap perhatikan dalam metrik kinerja

[-] Total buffer: 34.0M global + 2.7M per utas (1050 maks utas)

bahwa MySQL dapat mengalokasikan hingga 72% dari RAM yang dipasang berdasarkan pengaturan di /etc/my.cnf.

34M didasarkan pada innodb_buffer_pool_size dan key_buffer_size digabungkan

2,7M per utas didasarkan pada read_buffer_size + read_rnd_buffer_size + sort_buffer_size + join_buffer_size.

Kelipatan 2.7M didasarkan pada max_connections.

Oleh karena itu, Anda harus mengubah parameter ini hingga laporan metrik Kinerja mengatakan Anda memiliki di bawah 100% (lebih disukai di bawah 80%) dari RAM yang terpasang.

RolandoMySQLDBA
sumber
Saya tidak yakin saya bisa menggunakan alat Anda; Saya menggunakan Windows. Dokumentasi menyebutkan bahwa Windows tidak didukung, tetapi saya tetap mencoba. Ketika saya mencoba menjalankannya, ini menunjukkan bahwa itu tidak dapat menemukan mysqladmin di $ PATH saya, tetapi direktori bin MySQL memang di $ PATH saya.
Michael McGowan
Maaf, saya tidak melihat datadir Windows. Saya akan menambahkan jawaban yang berbeda.
RolandoMySQLDBA
1

Anda tidak mengatakan berapa banyak RAM yang Anda miliki? Saya menganggap itu setidaknya 32GB.

innodb_buffer_pool_size - 23G

Bagus untuk RAM sebesar itu.

query_cache_size = 1G

Terlalu besar. Itu tidak efisien ketika itu besar. Rekomendasikan tidak lebih dari 50 juta.

key-buffer_size = 5G

Mungkin ada batas keras 4G (masih) di Windows, punya batas keras 4G. 5G Anda mungkin telah berubah menjadi 1G. Lagi pula, jika semua meja Anda adalah InnoDB, mengapa buang domba jantan itu. Atur ke 50 juta.

Karena pesan kesalahan memiliki tepat 1G, baunya seperti sort_buffer_size. 32M mungkin masuk akal.

Rick James
sumber