Mysql perlahan menggunakan memori sampai mulai menggunakan swap


8

Saya menjalankan server database RAM rackspace 1gb. Untuk beberapa alasan dalam sekitar 2 hari penggunaan memori beralih dari menggunakan sangat sedikit swap, hingga menggunakan 100mb. Jika saya tidak me-restart sql akan tetap menggunakan lebih banyak swap. (File my.cnf saya ditampilkan di bawah dan penggunaan memori ditunjukkan di bawah)

Beberapa latar belakang: Saya memiliki sekitar 50 database aktif yang memiliki skema yang sama yang menggunakan INNODB untuk tabel di sana. Saya memiliki beberapa basis data dengan sedikit lalu lintas yang menggunakan MyISAM.

Pada tabel INNODB saya TIDAK menggunakan koneksi persisten. Saya juga memiliki fungsi pelaporan yang membuat tabel sementara. (Ini bisa menjadi sumber daya intensif, tetapi TIDAK sering terjadi)

Saya menggunakan CENTOS 6.3 dan mysql 5.5.28-log

Meskipun saya menggunakan swap, kinerjanya masih cukup bagus. Saya hanya takut jika saya tidak me-restart setiap beberapa hari saya akan memiliki masalah.

Berikut ini adalah log gratis -m saya selama sekitar 2 hari: (Catatan pertama tepat setelah restart mysql)

12/26 2:08 PM EST
             total       used       free     shared    buffers     cached
Mem:           992        697        295          0         74        362
-/+ buffers/cache:        260        732
Swap:          976         15        961

12/26 4:10 PM EST
[root@php-pos-db ~]# free -m
             total       used       free     shared    buffers     cached
Mem:           992        791        201          0         97        405
-/+ buffers/cache:        287        705
Swap:          976         14        961

12/27 2:52 PM EST
[root@php-pos-db ~]# free -m
             total       used       free     shared    buffers     cached
Mem:           992        947         45          0         55        169
-/+ buffers/cache:        722        270
Swap:          976         34        942

12/28 1:41 PM EST
             total       used       free     shared    buffers     cached
Mem:           992        963         29          0         45        119
-/+ buffers/cache:        797        195
Swap:          976         48        927

12/28 7:24 PM EST
[root@php-pos-db ~]# free -m
             total       used       free     shared    buffers     cached
Mem:           992        957         35          0         41        141
-/+ buffers/cache:        774        218
Swap:          976         90        886

12/28 8:33 PM EST
[root@php-pos-db ~]# free -m
             total       used       free     shared    buffers     cached
Mem:           992        948         44          0         48        130
-/+ buffers/cache:        768        224
Swap:          976         96        880

my.cnf

# The MySQL database server configuration file.
#
# You can copy this to one of:
# - "/etc/mysql/my.cnf" to set global options,
# - "~/.my.cnf" to set user-specific options.
# 
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html
#
# Take care to only add/remove/change a setting if you are comfortable
# doing so! For Rackspace customers, if you have any questions or
# concerns, please contact the MySQL Database Services Team. Be aware
# that some work performed by this team can involve additional billable
# fees.
#
# This file generated for host php-pos-db please modify
# variables if the server is resized from 1016636kB

[mysqld]

### General
user                = mysql
port                = 3306
datadir                         = /var/lib/mysql
tmpdir                          = /tmp
socket                          = /var/lib/mysql/mysql.sock
skip-external-locking           = 1
log_error                       = /var/log/mysqld.log

## This prevents using host-based authentication. That means users must be
## created using an ip-address (ie 'myuser'@'192.168.100.1') or must make
## use of the % wildcard (ie 'myuser'@'%'). The benefit to not using
## host-based authentication is that DNS will not impact MySQL performance.
#skip-name-resolve

## If open-files-limit is set very low, MySQL may increase on its own. Either
## way, increase this if MySQL gives 'too many open files' errors. Setting
## this above 65535 could be unwise (MySQL may crash).
open-files-limit                = 20000

### Cache
thread-cache-size               = 16
table-open-cache                = 4096
table-definition-cache          = 512

## Generally, it is unwise to set the query cache to be larger than 64-128M 
## as the costs associated with maintaining the cache outweigh the performance
## gains. A far superior solution would be to implement memcached, though this
## required modifying the application, among other things.
query-cache-type                = 1
query-cache-size                = 32M
query-cache-limit               = 1M

### Per-thread Buffers
sort-buffer-size                = 1M
read-buffer-size                = 1M
read-rnd-buffer-size            = 2M
join-buffer-size                = 1M

### Temp Tables
tmp-table-size                  = 64M 
max-heap-table-size             = 64M

### Networking
back-log                        = 100
max-connections                 = 50
max-connect-errors              = 10000
max-allowed-packet              = 16M
interactive-timeout             = 600
wait-timeout                    = 180
net_read_timeout        = 30
net_write_timeout       = 30
# This value is the size of the listen queue for incoming TCP/IP connections.
back_log            = 128

#### Storage Engines
## Set this to force MySQL to use a particular engine / table-type
## for new tables. This setting can still be overridden by specifying
## the engine explicitly in the CREATE TABLE statement.
default-storage-engine         = InnoDB

## Makes sure MySQL does not start if InnoDB fails to start. This helps
## prevent ugly silent failures.
innodb                          = FORCE

### MyISAM
## Not sure what to set this to?
## Try running a 'du -sch /var/lib/mysql/*/*.MYI'
## This will give you a good estimate on the size of all the MyISAM indexes.
## (The buffer may not need to set that high, however)
key-buffer-size                 = 2M
## This setting controls the size of the buffer that is allocated when 
## sorting MyISAM indexes during a REPAIR TABLE or when creating indexes 
## with CREATE INDEX or ALTER TABLE.
myisam-sort-buffer-size         = 2M

### InnoDB
## Note: While most settings in MySQL can be set at run-time, many InnoDB
## variables cannot be set at runtime as require restarting MySQL
###
## These settings control how much RAM InnoDB will use. Generally, when using
## mostly InnoDB tables, the innodb-buffer-pool-size should be as large as
## is possible without swapping or starving other processes of RAM. The other 
## two settings usually do not need to be changed, but can help for very large 
## datasets.
innodb-buffer-pool-size         = 285M
innodb-log-buffer-size          = 8M

## Be careful when changing these as they require re-generating the 
## ib-logfile* files, which must be done carefully. Do not change this unless 
## you are familiar with the procedure.
innodb-log-file-size           = 128M
innodb-log-files-in-group      = 2

## This will cause each table to create its own .ibd file
innodb-file-per-table           = 1

## Setting this to 2 will decrease disk I/O but can cause up to a second of
## queries to be lost during a hard outage (i.e. power failures)
# innodb-flush-log-at-trx-commit = 2

### Replication
## Set this to the Server's instance ID in replication environments
server-id                       = 1

#log-bin                        = /var/lib/mysql/bin-log
#relay-log                      = /var/lib/mysql/relay-log
#relay-log-space-limit          = 4G
#expire-logs-days               = 5

## This should be enabled on conventional MySQL slaves
#read-only                      = 1

## This will cause replicated statements on a slave to be written to the slave's binlog
## Enable this on the middle slave of M->S->S configs
#log-slave-updates              = 1

#binlog-format                  = STATEMENT

### Logging
## This option determines the destination for general query log and slow query log output.
## The option value can be given as one or more of the words TABLE, FILE, or NONE.
## NOTE: Table logging takes away 50% of performance and thus is not recommended
##       http://bugs.mysql.com/bug.php?id=30414
## In addition, you cannot backup the contents of these tables properly
## (mysqldump skips these tables by default since they cannot be locked)
#log-output                     = FILE
slow-query-log                 = 1
slow-query-log-file            = /var/lib/mysql/slow-log
long-query-time                = 2
log-queries-not-using-indexes  = 1

[mysqld-safe]
log-error                       = /var/log/mysqld.log

[mysqldump]
max-allowed-packet      = 16M

# * IMPORTANT: Additional settings that can override those from this file!
#   The files must end with '.cnf', otherwise they'll be ignored.
#
!includedir /etc/sysconfig/mysqld-config/

Jawaban:


5

MySQL memang memiliki kebiasaan buruk menjadi swap-happy. Jeremy Cole telah membahas hal ini dengan baik di blognya: http://blog.jcole.us/2012/04/16/a-brief-update-on-numa-and-mysql/ . Dari blog itu, Anda belajar bahwa ada sesuatu yang dapat Anda lakukan: Tambahkan numactl --interleave=alldi dalam /etc/init.d/mysql.

SARAN

Jika Server didedikasikan untuk hanya melakukan MySQL, silakan ubah yang berikut di /etc/my.cnf:

[mysqld]
innodb_open_files=1000
innodb_flush_method=O_DIRECT
innodb_buffer_pool_size=768M
innodb_log_file_size=192M

Jika server setidaknya memiliki dual-core, tambahkan ini

innodb_buffer_pool_instances=2
innodb_read_io_threads=16
innodb_write_io_threads=16
innodb_io_capacity=2000

Selanjutnya, login ke mysql run SET GLOBAL innodb_fast_shutdown = 0;

Selanjutnya, jalankan yang berikut di OS

cd /var/lib/mysql
service mysql stop
mv ib_logfile0 ib_logfile0.bak
mv ib_logfile1 ib_logfile1.bak
service mysql start

Cobalah !!!

UPDATE 2012-12-31 08:30 EDT

Dari komentar terakhir Anda

Itu berhenti mendaki sekitar 1 gb. Saya menghapus database yang tidak digunakan dan sepertinya mysql 5.5 menyimpan banyak data dalam memori karena ini tidak terjadi pada 5.0. Apakah mysql banyak berubah?

Ya, MySQL telah banyak berubah. Bahkan, ada banyak kasus di mana peningkatan dari MySQL 5.0 ke MySQL 5.5 dan mengakibatkan penurunan kinerja. InnoDB 5.5 sekarang dilengkapi untuk melakukan hyperthreading dan multicore engagement.

Percona benar-benar menguji ini beberapa waktu yang lalu .

Tolong baca saya posting terakhir tentang hal ini

Saya juga menulis tentang ini di ServerFault dan StackOverflow


Saya akan coba ini: Apa perbedaan antara innodb_buffer_pool_size dan innodb-buffer-pool-size
Chris Muench

innodb_buffer_pool_size768M mungkin mendorong batas pada mesin dengan hanya 1 GB RAM. Hanya 256 juta yang tersisa untuk apa pun yang terjadi di kernel dan ruang pengguna di luar MySQL, ditambah semua yang terjadi di MySQL di luar kumpulan buffer InnoDB ... Anda perlu mengatur itu untuk sesuatu tetapi jujur ​​saya akan mencari mendapatkan lebih banyak memori demikian juga.
James L

FWIW, NUMA seharusnya tidak menjadi faktor di sini: mesin 1 GB di Rackspace yang menjalankan CentOS 6.3 akan menjadi VM dengan hanya satu simpul NUMA yang disajikan.
James L

@ James karena ini VM, Anda benar. Tuning multicore tidak perlu dan 75% RAM pada 1GB terlalu rendah. Ia membutuhkan setidaknya 4GB.
RolandoMySQLDBA

Saya memutakhirkan ke server rackspace 2gb dan penggunaan memori masih naik. Kami bingung dengan apa yang terjadi. Ini TIDAK terjadi di mysql 5.0.96
Chris Muench

0

Terlepas dari saran yang sangat baik yang diberikan oleh Rolando, Anda dapat, di sisi sistem, mengaktifkan pengaturan swap-less menggunakan sysctl . Saya biasanya mengatur vm.swappiness=10mesin MySQL di /etc/sysctl.conf . Ini memberikan akses terbatas ke swap, tetapi mengizinkannya jika diperlukan.

Nilai default dari vm.swappiness adalah 60, yang sangat permisif.


0

Catatan : Saya mengirim jawaban ini ke pertanyaan terkait tentang stackoverflow. Solusi ini spesifik untuk Linux dan Systemd, tetapi pada kenyataannya, dapat diadaptasi untuk sistem apa pun yang mendukung memlockpanggilan dengan benar dan memberikan kemampuan untuk melakukannya untuk proses yang tidak tetap root.

Pembaruan : Solusi ini mungkin tidak bekerja dengan baik. Lihat catatan di akhir.

Ada kelas aplikasi di mana Anda tidak ingin mereka bertukar. Salah satu kelas tersebut adalah database. Database akan menggunakan memori sebagai cache dan buffer untuk area disk mereka, dan sama sekali tidak masuk akal bahwa ini pernah ditukar. Memori tertentu dapat menampung beberapa data relevan yang tidak diperlukan selama seminggu hingga suatu hari ketika klien memintanya. Tanpa caching / swapping, database hanya akan menemukan catatan yang relevan pada disk, yang akan cukup cepat; tetapi dengan bertukar, layanan Anda mungkin tiba-tiba membutuhkan waktu lama untuk merespons.

mysqldtermasuk kode untuk menggunakan OS / panggilan sistem memlock. Di Linux, setidaknya sejak 2.6.9, panggilan sistem ini akan berfungsi untuk proses non-root yang memiliki CAP_IPC_LOCKkapabilitas [1] . Saat menggunakan memlock(), proses tersebut masih harus bekerja dalam batas LimitMEMLOCKbatas. [2] . Salah satu (beberapa) hal baik tentang systemdadalah bahwa Anda dapat memberikan mysqldproses kemampuan ini, tanpa memerlukan program khusus. Jika juga dapat mengatur rlimits seperti yang Anda harapkan ulimit. Berikut adalah overridefile untuk mysqldyang melakukan langkah-langkah yang diperlukan, termasuk beberapa yang lain yang mungkin Anda perlukan untuk proses seperti database:

[Service]
# Prevent mysql from swapping
CapabilityBoundingSet=CAP_IPC_LOCK

# Let mysqld lock all memory to core (don't swap)
LimitMEMLOCK=-1 

# do not kills this process if low on memory
OOMScoreAdjust=-900 

# Use higher io scheduling
IOSchedulingClass=realtime    

Type=simple    
ExecStart=
ExecStart=/usr/sbin/mysqld --memlock $MYSQLD_OPTS

Catatan Komunitas standar mysql saat ini dikirimkan dengan Type=forking dan menambahkan --daemonizeopsi ke layanan di ExecStarttelepon. Ini secara inheren kurang stabil daripada metode di atas.

Tentang Override file di systemd : Anda membuat direktori dengan /etc/systemd/system/nama mysqld.service.ddan menempatkan file baru (dengan konten di atas) ke dalamnya.

PEMBARUAN Saya tidak 100% senang dengan solusi ini. Setelah beberapa hari runtime, saya perhatikan prosesnya masih memiliki pertukaran yang sangat besar! Meneliti /proc/XXXX/smaps, saya perhatikan hal berikut:

  • Kontributor swap terbesar adalah dari segmen tumpukan! Awalnya ini sepertinya tidak terlalu buruk, tetapi setelah beberapa hari, itu berdiri di 437 MB dan berfluktuasi. Ini menyajikan masalah kinerja yang jelas. Ini juga menunjukkan kebocoran memori berbasis stack.
  • Tidak ada halaman Terkunci . Ini menunjukkan memlockopsi di MySQL (atau Linux) rusak. Dalam hal ini, tidak masalah karena MySQL tidak dapat memlock stack.
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.