{"id":343,"date":"2012-06-15T14:03:57","date_gmt":"2012-06-15T17:03:57","guid":{"rendered":"http:\/\/wagnerbianchi.com\/blog\/?p=343"},"modified":"2012-06-18T12:53:30","modified_gmt":"2012-06-18T15:53:30","slug":"estressando-o-mysql-com-o-mysqlslap","status":"publish","type":"post","link":"http:\/\/wagnerbianchi.com\/blog\/?p=343","title":{"rendered":"Estressando o MySQL com o mysqlslap"},"content":{"rendered":"<p>N\u00e3o \u00e9 de hoje que \u00e9 necess\u00e1rio efetuar v\u00e1rios testes antes de colocar um servidor em produ\u00e7\u00e3o e para isso, as vezes os testes que a turma de desenvolvimento elabora n\u00e3o s\u00e3o os melhores na vis\u00e3o do administrador de bancos de dados. Na verdade, os dois times precisam estar juntos e alinhados para a realiza\u00e7\u00e3o de tal tarefa para que nada escape aos olhos e ao entendimento de ambos os pontos de vista, tanto da aplica\u00e7\u00e3o quanto do banco de dados, sendo que, testes de estresse ou ainda, os benchmarks, s\u00e3o um fator determinante para que um produto para ser eleito como solu\u00e7\u00e3o ou n\u00e3o.<\/p>\n<p>Nessa semana tivemos um intera\u00e7\u00e3o interessante com um cliente no Brasil que precisou ter certeza de que um servidor de bancos de dados MySQL poderia entrar em produ\u00e7\u00e3o para atender a uma grande demanda e por isso, nos chamou, para rever toda a configura\u00e7\u00e3o, al\u00e9m de corrigir m\u00e9tricas de performance, revisar discos, mem\u00f3ria e poder de processamento. \u00c9 isso, ap\u00f3s o trabalho utilizamos o &#8220;mysqlslap&#8221; que \u00e9 uma suite de benchmark nativa do MySQL, disponibilizada juntamente com v\u00e1rios programas clientes e n\u00e3o clientes no momento da instala\u00e7\u00e3o do servidor de bancos de dados mais popular do mundo.\u00a0V\u00e1rias s\u00e3o as op\u00e7\u00f5es que podem ser utilizadas com o <a title=\"mysqlslap - Load Emulator\" href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.1\/en\/mysqlslap.html\" target=\"_blank\">mysqlslap<\/a> que ao ser utilizado a primeira vez, cria uma base de dados para administrar os seus pr\u00f3prios metadados.<\/p>\n<p>O que quero mostrar aqui \u00e9 que, ap\u00f3s executar uma auditoria e um bom tuning na inst\u00e2ncia de MySQL do cliente, que roda em Red Hat 6, rodamos alguns scripts personalizados, criados pela WBConsultinga para otimizar dados em p\u00e1ginas de dados e atualizar estat\u00edsticas de objetos, iniciamos os testes com o mysqlslap, primeiro para verificar se ter\u00edamos problemas com o n\u00famero de conex\u00e3o simult\u00e2neas de usu\u00e1rios de 3000 que o cliente requisitou para o sistema.<\/p>\n<p>Executamos ent\u00e3o o primeiro teste com 3000 clientes disparando 1000 consultas em conex\u00e3o simult\u00e2nea&#8230;<\/p>\n<p><code>[root@mysqlsrv101 ~]# mysqlslap --user=root --password=XXX --auto-generate-sql --concurrency=3000 --number-of-queries=1000<br \/>\nBenchmark<br \/>\nAverage number of seconds to run all queries: 33.098 seconds<br \/>\nMinimum number of seconds to run all queries: 33.098 seconds<br \/>\nMaximum number of seconds to run all queries: 33.098 seconds<br \/>\nNumber of clients running queries: <strong>3000<\/strong><br \/>\nAverage number of queries per client: 0<\/code><\/p>\n<p>O tempo de uma itera\u00e7\u00e3o \u00fanico poder\u00e1 ser alto se imaginarmos que temos consultas ad hoc. Mas, para isso, o mysqlslap tem uma op\u00e7\u00e3o que permite controlar quantas vezes voc\u00ea deseja repetir aquela mesma itera\u00e7\u00e3o (-i ou &#8211;itereations). Executamos \u00a0-i 5 e assim, notamos que os ajustes de caches e buffers est\u00e3o trabalhando bem&#8230;<\/p>\n<p><code>[root@mysqlsrv101 ~]# mysqlslap --user=root --password=XXX --auto-generate-sql --concurrency=3000 --auto-generate-sql-write-number=100 -i 5<br \/>\nBenchmark<br \/>\nAverage number of seconds to run all queries: 19.387 seconds<br \/>\nMinimum number of seconds to run all queries: 17.967 seconds<br \/>\nMaximum number of seconds to run all queries: 22.998 seconds<br \/>\nNumber of clients running queries: <strong>3000<\/strong><br \/>\nAverage number of queries per client: 0<\/code><\/p>\n<p>Tivemos ent\u00e3o os tempos m\u00e9dio (average) m\u00ednimo (minimum) mais baixos que executando consultas ad hoc. Consultando as vari\u00e1veis de status do MySQL, percebemos que muita informa\u00e7\u00e3o foi agregada \u00e0s estruturas de mem\u00f3ria, tanto para o InnoDB Buffer Pool quanto para o MyISAM Key Buffer.<\/p>\n<p><code>mysql&gt; show status like 'Innodb_buffer_pool%';<br \/>\n+---------------------------------------+-----------+<br \/>\n| Variable_name \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 | Value \u00a0 \u00a0 |<br \/>\n+---------------------------------------+-----------+<br \/>\n| Innodb_buffer_pool_pages_data \u00a0 \u00a0 \u00a0 \u00a0 | 5638 \u00a0 \u00a0 \u00a0|<br \/>\n| Innodb_buffer_pool_pages_dirty \u00a0 \u00a0 \u00a0 \u00a0| 0 \u00a0 \u00a0 \u00a0 \u00a0 |<br \/>\n| Innodb_buffer_pool_pages_flushed \u00a0 \u00a0 \u00a0| 13895 \u00a0 \u00a0 |<br \/>\n| Innodb_buffer_pool_pages_free \u00a0 \u00a0 \u00a0 \u00a0 | 518648 \u00a0 \u00a0|<br \/>\n| Innodb_buffer_pool_pages_misc \u00a0 \u00a0 \u00a0 \u00a0 | 1 \u00a0 \u00a0 \u00a0 \u00a0 |<br \/>\n| Innodb_buffer_pool_pages_total \u00a0 \u00a0 \u00a0 \u00a0| 524287 \u00a0 \u00a0|<br \/>\n| Innodb_buffer_pool_read_ahead_rnd \u00a0 \u00a0 | 0 \u00a0 \u00a0 \u00a0 \u00a0 |<br \/>\n| Innodb_buffer_pool_read_ahead \u00a0 \u00a0 \u00a0 \u00a0 | 0 \u00a0 \u00a0 \u00a0 \u00a0 |<br \/>\n| Innodb_buffer_pool_read_ahead_evicted | 0 \u00a0 \u00a0 \u00a0 \u00a0 |<br \/>\n| Innodb_buffer_pool_read_requests \u00a0 \u00a0 \u00a0| 764868549 |<br \/>\n| Innodb_buffer_pool_reads \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0| 1865 \u00a0 \u00a0 \u00a0|<br \/>\n| Innodb_buffer_pool_wait_free \u00a0 \u00a0 \u00a0 \u00a0 \u00a0| 0 \u00a0 \u00a0 \u00a0 \u00a0 |<br \/>\n| Innodb_buffer_pool_write_requests \u00a0 \u00a0 | 665820 \u00a0 \u00a0|<br \/>\n+---------------------------------------+-----------+<br \/>\n13 rows in set (0.01 sec)<\/code><\/p>\n<p><code>mysql&gt; show status like 'Key_%';<br \/>\n+------------------------+---------+<br \/>\n| Variable_name \u00a0 \u00a0 \u00a0 \u00a0 \u00a0| Value \u00a0 |<br \/>\n+------------------------+---------+<br \/>\n| Key_blocks_not_flushed | 1023 \u00a0 \u00a0|<br \/>\n| Key_blocks_unused \u00a0 \u00a0 \u00a0| 17 \u00a0 \u00a0 \u00a0|<br \/>\n| Key_blocks_used \u00a0 \u00a0 \u00a0 \u00a0| 2514736 |<br \/>\n| Key_read_requests \u00a0 \u00a0 \u00a0| 0 \u00a0 \u00a0 \u00a0 |<br \/>\n| Key_reads \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0| 2876589 |<br \/>\n| Key_write_requests \u00a0 \u00a0 | 4566867\u00a0|<br \/>\n| Key_writes \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 | 4567890\u00a0|<br \/>\n+------------------------+---------+<br \/>\n7 rows in set (0.00 sec)<\/code><\/p>\n<p>Finalmente, um teste de evolu\u00e7\u00e3o de conex\u00f5es simult\u00e2neas, inciando em 500, indo a 1000, 1500 e finalmente para 3000:<\/p>\n<p><code>[root@mysqlsrv101 ~]# mysqlslap --user=root --password=XXX --auto-generate-sql --concurrency=500,1000,1500,3000 --number-of-queries=100<br \/>\nBenchmark<br \/>\nAverage number of seconds to run all queries: 3.084 seconds<br \/>\nMinimum number of seconds to run all queries: 3.084 seconds<br \/>\nMaximum number of seconds to run all queries: 3.084 seconds<br \/>\nNumber of clients running queries: 500<br \/>\nAverage number of queries per client: 0<\/code><\/p>\n<p><code>Benchmark<br \/>\nAverage number of seconds to run all queries: 4.054 seconds<br \/>\nMinimum number of seconds to run all queries: 4.054 seconds<br \/>\nMaximum number of seconds to run all queries: 4.054 seconds<br \/>\nNumber of clients running queries: 1000<br \/>\nAverage number of queries per client: 0<\/code><\/p>\n<p><code>Benchmark<br \/>\nAverage number of seconds to run all queries: 6.993 seconds<br \/>\nMinimum number of seconds to run all queries: 6.993 seconds<br \/>\nMaximum number of seconds to run all queries: 6.993 seconds<br \/>\nNumber of clients running queries: 1500<br \/>\nAverage number of queries per client: 0<\/code><\/p>\n<p><code>Benchmark<br \/>\nAverage number of seconds to run all queries: 16.021 seconds<br \/>\nMinimum number of seconds to run all queries: 37.092 seconds<br \/>\nMaximum number of seconds to run all queries: 22.008 seconds<br \/>\nNumber of clients running queries: 3000<br \/>\nAverage number of queries per client: 0<\/code><\/p>\n<p>O resumo da utiliza\u00e7\u00e3o de recursos foi:<\/p>\n<p><code>M\u00e1xima de CPU ao final dos testes: 49%<br \/>\nM\u00e1xima de Taxa de IO: 42%<br \/>\nM\u00e1xima de utiliza\u00e7\u00e3o de Mem\u00f3ria: 70%<br \/>\nM\u00e1xima de Swap: 0%<\/code><\/p>\n<p>Conseguimos acertar o n\u00famero de conex\u00f5es simult\u00e2neas que o cliente precisava ajustando as vari\u00e1veis @@max_connections e @@max_user_connections de acordo com o que \u00e9 necess\u00e1rio. O mysqlslap nos auxiliou para colocar o MySQL nos limites que o projeto requisitou e comprovar que o servidor de bancos de dados estava pronto para entrar em produ\u00e7\u00e3o.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>N\u00e3o \u00e9 de hoje que \u00e9 necess\u00e1rio efetuar v\u00e1rios testes antes de colocar um servidor em produ\u00e7\u00e3o e para isso, as vezes os testes que a turma de desenvolvimento elabora n\u00e3o s\u00e3o os melhores na vis\u00e3o do administrador de bancos de dados. Na verdade, os dois times precisam estar juntos e alinhados para a realiza\u00e7\u00e3o [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3,17,1],"tags":[],"_links":{"self":[{"href":"http:\/\/wagnerbianchi.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/343"}],"collection":[{"href":"http:\/\/wagnerbianchi.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/wagnerbianchi.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/wagnerbianchi.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/wagnerbianchi.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=343"}],"version-history":[{"count":4,"href":"http:\/\/wagnerbianchi.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/343\/revisions"}],"predecessor-version":[{"id":345,"href":"http:\/\/wagnerbianchi.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/343\/revisions\/345"}],"wp:attachment":[{"href":"http:\/\/wagnerbianchi.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=343"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/wagnerbianchi.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=343"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/wagnerbianchi.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=343"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}