Estoy ejecutando un servidor de base de datos de 1 gb de RAM en rack. Por alguna razón, en aproximadamente 2 días, el uso de la memoria pasa de usar muy poco intercambio a 100mb. Si no reinicio sql, seguirá usando más intercambio. (Mi archivo my.cnf se muestra a continuación y el uso de memoria se muestra a continuación)
Algunos antecedentes: tengo alrededor de 50 bases de datos activas que tienen el mismo esquema que usan INNODB para sus tablas. Tengo un par de bases de datos con poco tráfico que usan MyISAM.
En las tablas INNODB NO uso conexiones persistentes. También tengo una función de informes que crea una tabla temporal. (Esto puede requerir muchos recursos, pero NO sucede con frecuencia)
Estoy usando CENTOS 6.3 y mysql 5.5.28-log
Aunque estoy usando el intercambio, el rendimiento sigue siendo bastante bueno. Solo tengo miedo de que si no reinicio cada pocos días tendré un problema.
Aquí está mi registro de free -m durante aproximadamente 2 días: (El primer registro es justo después de un reinicio de 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/
fuente
innodb_buffer_pool_size
de 768M podría estar empujando el límite en una máquina con solo 1 GB de RAM. Solo quedan 256M para lo que sea que esté sucediendo en el kernel y el espacio de usuario fuera de MySQL, además de todo lo que está sucediendo en MySQL fuera del grupo de búferes InnoDB ... Necesitas configurar eso en algo pero honestamente estaría buscando obtener más memoria también.Además de los muy buenos consejos dados por Rolando, puede, en el lado del sistema, activar una configuración sin intercambio utilizando sysctl . Normalmente configuro
vm.swappiness=10
en la máquina MySQL en /etc/sysctl.conf . Da acceso restringido al intercambio, pero lo permite si es necesario.El valor predeterminado de vm.swappiness es 60, que es muy permisivo.
fuente
Nota : publiqué esta respuesta a una pregunta relacionada en stackoverflow. Esta solución es específica de Linux y Systemd, pero de hecho, se puede adaptar a cualquier sistema que admita
memlock
llamadas de manera adecuada y brinde la capacidad de hacerlo para procesos que no permanecen en la raíz.Actualización : esta solución podría, de hecho, no funcionar tan bien. Ver nota al final.
Existe una clase de aplicaciones en las que nunca desea que se intercambien. Una de esas clases es una base de datos. Las bases de datos utilizarán la memoria como cachés y memorias intermedias para sus áreas de disco, y no tiene absolutamente ningún sentido que se intercambien. La memoria particular puede contener algunos datos relevantes que no son necesarios durante una semana hasta un día cuando un cliente lo solicite. Sin el almacenamiento en caché / intercambio, la base de datos simplemente encontraría el registro relevante en el disco, lo que sería bastante rápido; pero con el intercambio, su servicio puede tardar mucho tiempo en responder.
mysqld
incluye código para usar la llamada del sistema operativo / sistema operativomemlock
. En Linux, desde al menos 2.6.9, esta llamada al sistema funcionará para procesos no root que tienen laCAP_IPC_LOCK
capacidad [1] . Cuando se usamemlock()
, el proceso aún debe funcionar dentro de los límites delLimitMEMLOCK
límite. [2] . Una de las (pocas) cosas buenassystemd
es que puede otorgarle almysqld
proceso estas capacidades, sin requerir un programa especial. Si también puede establecer los límites como es de esperar conulimit
. Aquí hay unoverride
archivomysqld
que realiza los pasos necesarios, incluidos algunos otros que podría necesitar para un proceso como una base de datos:Nota La comunidad estándar mysql actualmente se envía con
Type=forking
y agrega--daemonize
la opción al servicio enExecStart
línea. Esto es inherentemente menos estable que el método anterior.Acerca de la anulación de archivos en systemd : crea un directorio con
/etc/systemd/system/
nombremysqld.service.d
y coloca el nuevo archivo (con el contenido anterior) en él.ACTUALIZACIÓN No estoy 100% satisfecho con esta solución. ¡Después de varios días de tiempo de ejecución, noté que el proceso todavía tenía enormes cantidades de intercambio! Al examinarlo
/proc/XXXX/smaps
, observo lo siguiente:memlock
opción en MySQL (o Linux) está rota. En este caso, no importaría mucho porque MySQL no puede apilar memlock.fuente