Estamos ejecutando un sitio (Moodle) que los usuarios actualmente encuentran lento. Creo que he rastreado el problema hasta MySQL creando tablas temporales en el disco. Miro la variable created_tmp_disk_tables
en la administración del servidor Mysql Workbench y el número aumenta con aproximadamente 50 tablas / s. Después de un día de uso, created_tmp_disk_tables
es> 100k. Además, la memoria no parece ser liberada. El uso sigue aumentando hasta que el sistema se vuelve prácticamente inutilizable y tenemos que reiniciar MySQL. Necesito reiniciarlo casi todos los días y comienza con el uso de aproximadamente el 30-35% de la memoria disponible y termina el día con el 80%.
No tengo blobs en la base de datos y tampoco control sobre las consultas, así que no puedo intentar optimizarlas. También he usado el Asistente de confirmación de Percona para generar un archivo de configuración, pero my.ini tampoco resolvió mi problema.
Preguntas
¿Qué debo cambiar para evitar que MySQL cree tablas temporales en el disco? ¿Hay configuraciones que necesito cambiar? ¿Debería arrojarle más memoria?
¿Cómo puedo evitar que MySQL me coma la memoria?
Editar
Habilité el slow_queries
registro y descubrí que la consulta SELECT GET_LOCK()
se registró como lenta. Una búsqueda rápida reveló que había permitido conexiones persistentes en la configuración de PHP ( mysqli.allow_persistent = ON
). Apagué esto. Esto redujo la velocidad a la que MySQL consume memoria, aunque todavía está creando tablas temporales.
También verifiqué que key_buffer size
es lo suficientemente grande. Miré la variable key_writes
. Esto debería ser cero. Si no, aumente key_buffer_size
. Tengo cero key_reads
y cero, key_writes
así que supongo que key_buffer_size
es lo suficientemente grande.
Aumenté el tmp_table_size
y max-heap-table-size
al 1024M como un aumento en Created_tmp_disk_tables puede indicar que las tablas no pueden caber en la memoria. Esto no lo resolvió.
Editar 2
Si ve muchos sort_merge_passes
por segundo en la salida SHOW GLOBAL STATUS, puede considerar aumentar el sort_buffer_size
valor. Tenía 2 sort_merge_passes
en una hora, así que considero sort_buffer_size
que es lo suficientemente grande.
Ref: Mysql Manual sobre sort_buffer_size
Editar 3
He modificado la ordenación y unir buffers como lo sugiere @RolandoMySQLDBA. El resultado se muestra en la tabla a continuación, pero creo que created_tmp_tables_on_disk
todavía es alto. Reinicié el servidor mysql después de cambiar el valor y verifiqué created_tmp_tables_on_disk
después de un día (8h) y calculé el promedio. ¿Cualquier otra sugerencia? Me parece que hay algo que no cabe dentro de algún tipo de contenedor, pero no puedo entender qué es.
+---------------------+-------------+-------------+--------------------+
| Tmp_table_size, | Sort_buffer | Join_buffer | No of created |
| max_heap_table_size | | | tmp_tables on disk |
+---------------------+-------------+-------------+--------------------+
| 125M | 256K | 256K | 100k/h |
+---------------------+-------------+-------------+--------------------+
| 125M | 512K | 512K | 100k/h |
+---------------------+-------------+-------------+--------------------+
| 125M | 1M | 1M | 100k/h |
+---------------------+-------------+-------------+--------------------+
| 125M | 4M | 4M | 100k/h |
+---------------------+-------------+-------------+--------------------+
Esta es mi configuración:
+-----------------------+-----------------------+
|DATABASE SERVER |WEB SERVER |
+-----------------------+-----------------------+
|Windows Server 2008 R2 |Windows Server 2008 R2 |
+-----------------------+-----------------------+
|MySQL 5.1.48 |IIS 7.5 |
+-----------------------+-----------------------+
|4 Core CPU |4 Core CPU |
+-----------------------+-----------------------+
|4GB RAM |8GB RAM |
+-----------------------+-----------------------+
Información Adicional
+--------------------+---------+
|PARAM |VALUE |
+--------------------+---------+
|Num of tables in Db |361 |
+--------------------+---------+
|Size of database |2.5G |
+--------------------+---------+
|Database engine |InnoDB |
+--------------------+---------+
|Read/write ratio |3.5 |
|(Innodb_data_read/ | |
|innodb_data_written)| |
+--------------------+---------+
|Avg table size |15k rows |
+--------------------+---------+
|Max table size |744k rows|
+--------------------+---------+
Esta configuración me fue dada, así que tengo un control limitado sobre ella. El servidor web está usando muy poca CPU y RAM, así que he excluido esa máquina como un cuello de botella. La mayoría de la configuración de MySQL se origina en una herramienta de generación automática de configuración.
He monitoreado el sistema usando PerfMon durante algunos días representativos. A partir de eso, llego a la conclusión de que no es el sistema operativo el que está cambiando al disco.
My.ini
[client]
port=3306
[mysql]
default-character-set=utf8
[mysqld]
port=3306
basedir="C:/Program Files/MySQL/MySQL Server 5.1/"
datadir="D:/DBs/Data/"
default-character-set=utf8
default-storage-engine=INNODB
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
max_connections=125
query_cache_size=350M
table_cache=1520
tmp_table_size=125M
table-definition-cache= 1024
max-heap-table-size= 32M
thread_cache_size=38
MyISAM Specific options
myisam_max_sort_file_size=100G
myisam_sort_buffer_size=125M
key_buffer_size=55M
read_buffer_size=1024K
read_rnd_buffer_size=256K
sort_buffer_size=1024K
join_buffer_size=1024K
INNODB Specific options
innodb_data_home_dir="D:/DBs/"
innodb_additional_mem_pool_size=32M
innodb_flush_log_at_trx_commit=1
innodb_log_buffer_size=16M
innodb_buffer_pool_size=2G
innodb_log_file_size=407M
innodb_thread_concurrency=8