Estamos executando um site (Moodle) que os usuários acham lento no momento. Acho que localizei o problema no MySQL criando tabelas temporárias no disco. Observo a variável created_tmp_disk_tables
na administração do servidor Mysql Workbench e o número aumenta em aproximadamente 50 tabelas / s. Após um dia de uso, created_tmp_disk_tables
é> 100k. Além disso, a memória não parece ser liberada. O uso continua aumentando até que o sistema se torne praticamente inutilizável e precisamos reiniciar o MySQL. Preciso reiniciá-lo quase todos os dias e começa com o uso de 30 a 35% da memória disponível e o final do dia com 80%.
Não tenho blobs no banco de dados e não tenho controle sobre as consultas, portanto não posso tentar otimizá-las. Também usei o Assistente de confirmação da Percona para gerar um arquivo de configuração, mas o my.ini também não resolveu o meu problema.
Questões
O que devo mudar para impedir que o MySQL crie tabelas temporárias em disco? Existem configurações que preciso alterar? Devo jogar mais memória nele?
Como posso parar o MySQL de consumir minha memória?
Editar
Ativei o slow_queries
log e descobri que a consulta SELECT GET_LOCK()
estava registrada como lenta. Uma pesquisa rápida revelou que eu havia permitido conexões persistentes na configuração do PHP ( mysqli.allow_persistent = ON
). Eu desliguei isso. Isso reduziu a taxa na qual o MySQL consome memória, embora ainda esteja criando tabelas temporárias.
Eu também verifiquei se o key_buffer size
tamanho é grande o suficiente. Eu olhei para a variável key_writes
. Isso deve ser zero. Caso contrário, aumente o key_buffer_size
. Eu tenho zero key_reads
e zero, key_writes
então suponho que o número key_buffer_size
seja grande o suficiente.
Aumentei o tmp_table_size
e max-heap-table-size
para 1024M, pois um aumento no created_tmp_disk_tables pode indicar que as tabelas não podem caber na memória. Isso não resolveu.
Editar 2
Se você vir muitos sort_merge_passes
por segundo na saída SHOW GLOBAL STATUS, considere aumentar o sort_buffer_size
valor. Eu tinha 2 sort_merge_passes
em uma hora, então eu considero o sort_buffer_size
suficiente para ser grande.
Ref: Manual do Mysql sobre sort_buffer_size
Editar 3
Modifiquei a classificação e juntei os buffers, conforme sugerido por @RolandoMySQLDBA. O resultado é exibido na tabela abaixo, mas acho que created_tmp_tables_on_disk
ainda é alto. Reiniciei o servidor mysql depois de alterar o valor, verifiquei created_tmp_tables_on_disk
após um dia (8h) e calculei a média. Alguma outra sugestão? Parece-me que há algo que não cabe dentro de algum tipo de recipiente, mas não consigo descobrir o que é.
+---------------------+-------------+-------------+--------------------+
| 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 é a minha configuração:
+-----------------------+-----------------------+
|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 |
+-----------------------+-----------------------+
Informação 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|
+--------------------+---------+
Essa configuração foi dada a mim, então eu tenho controle limitado sobre ela. O servidor da Web está usando muito pouca CPU e RAM, então excluí essa máquina como gargalo. A maioria das configurações do MySQL se origina de uma ferramenta de geração automática de configuração.
Monitorei o sistema usando o PerfMon por alguns dias representativos. A partir disso, concluo que não é o SO que está trocando para o 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