Mysql utilizza lentamente la memoria fino a quando non inizia a utilizzare lo scambio


8

Sto eseguendo un server database da 1 GB di RAM. Per qualche motivo in circa 2 giorni l'utilizzo della memoria passa dall'uso di pochissimo swap all'utilizzo di 100mb. Se non riavvio sql continuerà a utilizzare più swap. (Il mio file my.cnf è mostrato sotto e l'utilizzo della memoria mostrato sotto)

Alcuni retroscena: ho circa 50 database attivi che hanno lo stesso schema che utilizza INNODB per le loro tabelle. Ho un paio di database con poco traffico che usano MyISAM.

Sulle tabelle INNODB NON uso connessioni persistenti. Ho anche una funzione di reporting che crea una tabella temporanea. (Questo può richiedere molte risorse, ma NON accade spesso)

Sto usando CENTOS 6.3 e mysql 5.5.28-log

Anche se sto usando lo swap, le prestazioni sono ancora piuttosto buone. Ho solo paura che se non riavvio ogni pochi giorni avrò un problema.

Ecco il mio log di free -m per circa 2 giorni: (Il primo record è subito dopo il riavvio di 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/

Risposte:


5

MySQL ha la cattiva abitudine di essere felice di scambiare. Jeremy Cole ha affrontato al meglio questo aspetto nel suo blog: http://blog.jcole.us/2012/04/16/a-brief-update-on-numa-and-mysql/ . Da quel blog, apprendi che c'è qualcosa che puoi fare: Aggiungi numactl --interleave=alldentro /etc/init.d/mysql.

SUGGERIMENTI

Se il server è dedicato a fare solo MySQL, modifica quanto segue in /etc/my.cnf:

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

Se il server è almeno dual-core, aggiungere questi

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

Quindi, accedi a mysql run SET GLOBAL innodb_fast_shutdown = 0;

Quindi, eseguire quanto segue nel sistema operativo

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

Provaci !!!

AGGIORNAMENTO 2012-12-31 08:30 EDT

Dal tuo ultimo commento

Ha smesso di arrampicarsi intorno a 1 GB. Ho rimosso i database inutilizzati e sembra che mysql 5.5 memorizzi molti dati in memoria poiché ciò non è avvenuto in 5.0. Mysql è cambiato molto?

Sì, MySQL è cambiato molto. In effetti, ci sono molti casi in cui l'aggiornamento da MySQL 5.0 a MySQL 5.5 e ha comportato un degrado delle prestazioni. InnoDB 5.5 è ora attrezzato per eseguire hyperthreading e il coinvolgimento multicore.

Percona lo ha effettivamente testato qualche tempo fa .

Per favore, leggimi i post precedenti su questo argomento

Ho anche scritto di questo in ServerFault e StackOverflow


Proverò questo: qual è la differenza tra innodb_buffer_pool_size e innodb-buffer-pool-size
Chris Muench,

innodb_buffer_pool_sizedi 768 M potrebbe spingere il limite su una macchina con solo 1 GB di RAM. Solo 256 M rimanenti per tutto ciò che sta succedendo nel kernel e nello spazio utente al di fuori di MySQL, oltre a tutto ciò che sta accadendo in MySQL al di fuori del pool di buffer InnoDB ... Devi impostarlo su qualcosa ma onestamente starei cercando di ottenere più memoria anche.
James L,

FWIW, NUMA non dovrebbe essere un fattore qui: una macchina da 1 GB su Rackspace che esegue CentOS 6.3 sarà una VM con un solo nodo NUMA presentato.
James L

@James dato che è una VM hai ragione. L'ottimizzazione multicore non è necessaria e il 75% della RAM su 1 GB è troppo basso. Ha bisogno di almeno 4 GB.
RolandoMySQLDBA

Ho eseguito l'aggiornamento a un server rackspace da 2 GB e l'utilizzo della memoria è ancora in aumento. Siamo sconcertati da ciò che sta accadendo. Questo NON è accaduto in mysql 5.0.96
Chris Muench il

0

Oltre all'ottimo consiglio dato da Rolando, è possibile, dal lato del sistema, attivare un'impostazione senza swap usando sysctl . Di solito imposto vm.swappiness=10sulla macchina MySQL in /etc/sysctl.conf . Dà accesso limitato allo swap, ma lo consente, se necessario.

Il valore predefinito di vm.swappiness è 60, che è molto permissivo.


0

Nota : ho inviato questa risposta a una domanda correlata su StackOverflow. Questa soluzione è specifica per Linux e Systemd, ma in realtà può essere adattata a qualsiasi sistema che supporti correttamente le memlockchiamate e fornisca la capacità di farlo per i processi che non rimangono root.

Aggiornamento : questa soluzione potrebbe, in effetti, non funzionare così bene. Vedi nota alla fine.

Esiste una classe di applicazioni in cui non si desidera che vengano scambiate. Una di queste classi è un database. I database utilizzeranno la memoria come cache e buffer per le loro aree del disco e non ha assolutamente senso che questi vengano mai scambiati. La memoria particolare può contenere alcuni dati rilevanti che non sono necessari per una settimana fino a un giorno quando un client lo richiede. Senza la memorizzazione nella cache / scambio, il database troverebbe semplicemente il record rilevante su disco, il che sarebbe abbastanza veloce; ma con lo scambio, il servizio potrebbe improvvisamente richiedere molto tempo per rispondere.

mysqldinclude il codice per utilizzare la chiamata del sistema operativo / memlock. Su Linux, almeno dal 2.6.9, questa chiamata di sistema funzionerà per i processi non root che hanno la CAP_IPC_LOCKcapacità [1] . Durante l'utilizzo memlock(), il processo deve ancora funzionare entro i limiti del LimitMEMLOCKlimite. [2] . Una delle (poche) cose positive systemdè che puoi concedere al mysqldprocesso queste capacità, senza richiedere un programma speciale. Se posso anche impostare i limiti come ti aspetteresti ulimit. Ecco un overridefile per mysqldquello che fa i passi necessari, inclusi alcuni altri che potresti aver bisogno per un processo come un 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

Nota La community standard mysql attualmente viene fornita con Type=forking e aggiunge --daemonizel'opzione al servizio sulla ExecStartlinea. Questo è intrinsecamente meno stabile del metodo sopra.

Informazioni su Sostituisci file in systemd : si crea una directory in /etc/systemd/system/nome mysqld.service.de si inserisce il nuovo file (con i contenuti sopra).

AGGIORNAMENTO Non sono soddisfatto al 100% con questa soluzione. Dopo diversi giorni di autonomia, ho notato che il processo aveva ancora enormi quantità di scambio! Esaminando /proc/XXXX/smaps, noto quanto segue:

  • Il maggiore collaboratore di swap proviene da un segmento di stack! All'inizio questo non sembrò poi così male, ma dopo diversi giorni si attestò a 437 MB e fluttuò. Ciò presenta ovvi problemi di prestazioni. Indica anche una perdita di memoria basata su stack.
  • Non ci sono pagine bloccate . Ciò indica che l' memlockopzione in MySQL (o Linux) non è attiva. In questo caso, non importerebbe molto perché MySQL non è in grado di memlock stack.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.