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
fonte
Respostas:
Olhando para o
my.ini
, eu tenho duas sugestõesSUGESTÃO # 1
Eu aumentaria as seguintes configurações no seu
my.ini
Isso fará com que algumas junções e a classificação fiquem na memória. Obviamente, uma vez que um
JOIN
ouORDER BY
mais precise mais4M
, ele paginará em disco como uma tabela MyISAM.Se você não pode logar como
root@localhost
, reinicie o mysql comSe você pode fazer login como root @ localhost, não precisa reiniciar o mysql para usar essas configurações.
Basta executar isso no cliente MySQL:
SUGESTÃO # 2
Como seus dados estão na unidade
D:
, você pode ter E / S de disco na unidadeC:
.Por favor, execute esta consulta:
Como eu executo o mysql na minha área de trabalho com os padrões, minhas tabelas temporárias estão sendo gravadas no Drive
C:
. Se a Unidade D for um disco melhor que a UnidadeC:
, talvez você possa mapear tabelas temporárias para a UnidadeD:
configurando tmpdir damy.ini
seguinte maneira:Você terá que reiniciar o mysql, pois tmpdir não é uma variável dinâmica.
De uma chance !!!
ATUALIZAÇÃO 29-11-2013 10:09 EST
SUGESTÃO # 3
Dado o fato de o MySQL estar em execução no Windows e você não poder tocar nas consultas do pacote principal, tenho duas idéias que devem ser feitas juntas.
IDÉIA # 1: Mover o banco de dados para uma máquina Linux
Você deve ser capaz de
IDÉIA # 2: Reconfigure o Moodle para apontar para a máquina Linux
O Moodle foi projetado para o LAMP em primeiro lugar. Apenas mude os arquivos de configuração para apontar para a máquina Linux em vez de localhost.
Aqui está um link para um documento antigo do Moodle 2.3 sobre como configurar o MySQL: http://docs.moodle.org/23/en/Installing_Moodle#Create_an_empty_database
Tenho certeza de que os documentos mais recentes também estão disponíveis.
Qual é o ponto de mover o banco de dados para o Linux ???
Como isso ajuda a situação da tabela temporária ???
Sugiro configurar um disco RAM como a pasta de destino para suas tabelas temporárias
Jan 04, 2013
: Existe um mecanismo ou truque MySQL para evitar gravar tantas tabelas temporárias no disco?Dec 17, 2012
: Por que o MySQL produz tantos arquivos MYD temporários? (Instruções reais)Nov 30, 2012
: É ruim criar várias tabelas temporárias mysql simultaneamente?A criação da tabela temporária ainda ocorrerá, mas será gravada na RAM e não no disco. reduzindo E / S de disco.
ATUALIZAÇÃO 29/11/2013 11:24 EST
SUGESTÃO # 4
Eu sugeriria revisitar a SUGESTÃO # 2 com um disco RAID-0 rápido (32+ GB), configurando-o como Drive T: (T for Temp). Depois de instalar esse disco, adicione-o a
my.ini
:Seria necessário reiniciar o MySQL, usando
BTW, eu disse RAID-0 de propósito, para que você possa obter um bom desempenho de gravação em um RAID-1, RAID-10. Um disco de tabela tmp não é algo que eu tornaria redundante.
Sem otimizar as consultas como @RaymondNijland comentou, você não pode reduzir a contagem de criação da tabela temporária de forma alguma.
SUGGESTION #3
eSUGGESTION #4
oferecer acelerar a criação da tabela temporária e a E / S da tabela temporária como a única alternativa.fonte
Eu respondo minha própria pergunta aqui por completude
Selecionarei @RolandoMySQLDBA como a resposta preferida, pois ele me deu mais dicas, embora não tenha realmente resolvido o meu problema.
Abaixo estão os resultados da minha investigação
Conclusão
O MySQL no Windows apenas cria muitas tabelas temporárias e o ajuste do MySQL ao modificar o conteúdo dos arquivos de configuração não ajudou.
Detalhes
A tabela detalha os parâmetros que eu modifiquei no my.ini, respectivamente, antes de executar qualquer consulta. O MySQL foi reiniciado entre cada teste.
Usei o my.ini encontrado na pergunta original como modelo e, em seguida, alterei o valor dos parâmetros um por um, de acordo com a tabela abaixo.
Eu usei o JMeter para gerar 100 solicitações da Web simultâneas (como isso representava nosso uso) repetidas 10 dez vezes. Cada um
Test
consistia em 1000 pedidos no total. Isso resultou em chamadas subseqüentes ao banco de dados. Isso mostrou que o MySQL criaria muitas tabelas temporárias, independentemente de quais parâmetros de configuração foram alterados.* Média de três execuções
As imagens abaixo mostram a quantidade de memória e CPU necessárias para o servidor de banco de dados para as diferentes configurações. As linhas pretas indicam os valores mínimo e máximo e as barras azuis indicam os valores inicial e final. A memória máxima foi a
4096M
indicada na pergunta.fonte