{"id":831,"date":"2013-11-28T12:38:54","date_gmt":"2013-11-28T15:38:54","guid":{"rendered":"http:\/\/wagnerbianchi.com\/blog\/?p=831"},"modified":"2013-11-28T12:38:54","modified_gmt":"2013-11-28T15:38:54","slug":"mysql-e-o-skip-name-resolve","status":"publish","type":"post","link":"http:\/\/wagnerbianchi.com\/blog\/?p=831","title":{"rendered":"MySQL e o skip-name-resolve"},"content":{"rendered":"<p>Desde o lan\u00e7amento da vers\u00e3o 5.5 do servidor de bancos de dados MySQL que eu venho verificando muitos problemas relacionados com a vari\u00e1vel de resolu\u00e7\u00e3o de nomes, skip-name-resolve. Para quem ainda n\u00e3o sabe ou est\u00e1 iniciando com o MySQL, toda vez que o servidor de bancos de dados recebe uma consulta, como por exemplo, aquela vinda do mysql client, o host de onde vem esta conex\u00e3o \u00e9 parte da verifica\u00e7\u00e3o de autentica\u00e7\u00e3o do usu\u00e1rio. Al\u00e9m do nome de usu\u00e1rio e a senha, o usu\u00e1rio dever\u00e1 ter permiss\u00e3o de originar uma conex\u00e3o de um determinado host, assim configurado atrav\u00e9s da cria\u00e7\u00e3o expl\u00edcita do usu\u00e1rio atrav\u00e9s do comando CREATE USER, ou, dependendo das configura\u00e7\u00e3o de SQL_MODE, usu\u00e1rios podem ser criados diretamente atrav\u00e9s do comando GRANT, este que permite que voc\u00ea tamb\u00e9m d\u00ea as devidas permiss\u00f5es e configure host e senha para o usu\u00e1rio.<\/p>\n<p>Voltando ent\u00e3o ao momento da conex\u00e3o, considerando que o host \u00e9 tamb\u00e9m verificado, na vers\u00e3o 5.5 uma nova feature foi apresentada, sendo adicionada para que hosts passassem permanecer em mem\u00f3ria cache. N\u00e3o s\u00f3 isso, como o MySQL verifica a exist\u00eancia do host vinculado a uma conex\u00e3o atrav\u00e9s da coluna host da tabela mysql.user, quando um host n\u00e3o existe, o MySQL tenta resolver o host atrav\u00e9s de um DNS Lookup. Primeiro ele resolve o IP em um nome de host e assim ele continua utilizando o IP, mas guarda no cache no cache o nome do host. Na resolu\u00e7\u00e3o do IP em nome, existe uma verifica\u00e7\u00e3o adicional: verificar se o IP que chegou no MySQL \u00e9 o mesmo IP configurado por tr\u00e1s do nome da m\u00e1quina configurado no DNS. Parece muito bom, mas, se na sua empresa voc\u00ea n\u00e3o utiliza um DNS ou mesmo, s\u00f3 tem endere\u00e7os de IP na coluna hosts da tabela mysql.user, talvez n\u00e3o seja necess\u00e1rio gerar um overhead para o servidor e tamb\u00e9m, um pouco de dor de cabe\u00e7a, pois, dependendo do tipo de monitoramento que voc\u00ea tem internamente, uma simples linha de um IP esse ou aquele adicionada ao error log, pode disparar um chamado desnecess\u00e1rio no meio da noite &#8211; olha, isso acontece!!<\/p>\n<p>Vantagens e desvantagens, se \u00e9 necess\u00e1rio que um usu\u00e1rio se conecte do endere\u00e7o BOX01 onde um dos requisitos \u00e9 criar um usu\u00e1rio &#8220;foo&#8221;@&#8221;box01&#8221;, tudo bem, vale ter a configura\u00e7\u00e3o. um outro ponto bastante interessante \u00e9 configurar o MySQL para que, caso um determinado usu\u00e1rio tentar conex\u00e3o por x vezes e n\u00e3o conseguir se logar no MySQL por conta de digita\u00e7\u00e3o errada ou mesmo esquecimento da senha, ele pode ser bloqueado (ningu\u00e9m sabe quando \u00e9 uma pessoa ou um rob\u00f4 tentando acesso). Isso poder\u00e1 ser realizado atrav\u00e9s da vari\u00e1vel max_connect_errors, que adicionada ao arquivo de configura\u00e7\u00e3o, com um valor 3, por exemplo, dar\u00e1 3 oportunidades de tentativa de login. Para desbloquear os hosts bloqueados, FLUSH HOSTS.<\/p>\n<p>Com a op\u00e7\u00e3o habilitada, o MySQL, al\u00e9m de fazer essa verifica\u00e7\u00e3o de IP (se ele \u00e9 ele mesmo!!), ainda ser\u00e1 utilizado um mecanismo de mem\u00f3ria para adicionar ao cache os hosts logo no primeiro acesso v\u00e1lido, sendo estes hosts mantidos em mem\u00f3ria at\u00e9 o espa\u00e7o para esta lista de hosts se esgotar. Nesse momento, o algoritmo LRU (<em>Least Recently Used<\/em>) \u00e9 acionado o host menos acessado \u00e9 despejado da mem\u00f3ria (processo conhecido como\u00a0<em>eviction<\/em>). \u00a0Todo esse processo tamb\u00e9m envolve estruturas como\u00a0<em>mutexes<\/em>,\u00a0<em>threads<\/em>\u00a0e\u00a0<em>locks<\/em>.<\/p>\n<p>Agora, caso os usu\u00e1rios que utilizam o MySQL possam ser criados considerando o IP de onde a conex\u00e3o \u00e9 gerada ou a string localhost, podemos desabilitar a resolu\u00e7\u00e3o de nomes com a vari\u00e1vel\u00a0<em>&#8211;skip-name-resolve<\/em>, adicionada \u00e0 sess\u00e3o [mysqld] do arquivo de configura\u00e7\u00e3o do MySQL e reinicie o mysqld.<\/p>\n<p><code>[mysqld]<br \/>\n<code>max_connect_errors=3 # tr\u00eas tentativas de autentica\u00e7\u00e3o<br \/>\n#skip-name-resolve \u00a0 # desabilita o DNS Lookup, linha comentada<\/code><\/code><\/p>\n<p>Interessante ressaltar que caso seja encontrado na coluna host das tabelas privil\u00e9gio (<em>user, db, host, tables_priv, columns_priv e procs_priv<\/em>) um valor diferente de um IP ou a string localhost, n\u00e3o \u00e9 aconselh\u00e1vel que a resolu\u00e7\u00e3o de nomes seja habilitada. Caso contr\u00e1rio, caso exista somente IPs e a string localhost,\u00a0<em>&#8211;skip-name-resolve<\/em>\u00a0poder\u00e1 ser desabilitado. use a consulta abaixo para verificar a exist\u00eancia de poss\u00edveis valores na coluna host nas tabelas de privil\u00e9gios do MySQL (tamb\u00e9m conhecidas como\u00a0<a title=\"Privilege System Grant Tables\" href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.1\/en\/grant-table-structure.html\" target=\"_blank\">grant tables<\/a>):<\/p>\n<p><code>mysql&gt; select a.host as `mysql.user`, b.host as `mysql.db`, c.host as `mysql.tables_priv`, d.host as `mysql.columns_pric` FROM mysql.user as a left join mysql.db as b on a.user=b.user left join mysql.tables_priv as c on a.user=c.user left join mysql.columns_priv as d on a.user=d.user;<br \/>\n+-----------------------+----------+-------------------+--------------------+<br \/>\n| mysql.user \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0| mysql.db | mysql.tables_priv | mysql.columns_pric |<br \/>\n+-----------------------+----------+-------------------+--------------------+<br \/>\n| localhost \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 | % \u00a0 \u00a0 \u00a0 \u00a0| NULL \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0| NULL \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 |<br \/>\n| localhost.localdomain | % \u00a0 \u00a0 \u00a0 \u00a0| NULL \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0| NULL \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 |<br \/>\n| localhost \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 | % \u00a0 \u00a0 \u00a0 \u00a0| NULL \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0| NULL \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 |<br \/>\n| localhost.localdomain | % \u00a0 \u00a0 \u00a0 \u00a0| NULL \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0| NULL \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 |<br \/>\n| 127.0.0.1 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 | NULL \u00a0 \u00a0 | NULL \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0| NULL \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 |<br \/>\n| ::1 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 | NULL \u00a0 \u00a0 | NULL \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0| NULL \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 |<br \/>\n| localhost \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 | NULL \u00a0 \u00a0 | NULL \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0| NULL \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 |<br \/>\n| localhost \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 | NULL \u00a0 \u00a0 | NULL \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0| NULL \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 |<br \/>\n| localhost.localdomain | NULL \u00a0 \u00a0 | NULL \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0| NULL \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 |<br \/>\n+-----------------------+----------+-------------------+--------------------+<br \/>\n9 rows in set (0.01 sec)<\/code><\/p>\n<p>No resultado da consulta acima, perceba que h\u00e1 muitos valores NULL em tabelas mais \u00e0 direita. Esse comportamento denota que n\u00e3o h\u00e1 usu\u00e1rios com permiss\u00f5es em de acesso restrito somente \u00e0 bancos de dados, \u00e0 tabelas de bancos de dados ou somente \u00e0 colunas de determinadas tabelas de bancos de dados espec\u00edficos.<\/p>\n<p>Quando o recurso est\u00e1 habilitado e o MySQL n\u00e3o consegue fazer o lookup reverso de conex\u00f5es, um evento de Warning \u00e9 adicionado ao log de erro &#8211; verifique a vari\u00e1vel error_log para saber aonde o arquivo de log foi criado &#8211; onde \u00e9 descrito que n\u00e3o foi poss\u00edvel resolver determinado IP\/DNS de uma conex\u00e3o. O erro que ser\u00e1 adicionado ao arquivo de log de erro do MySQL \u00e9 algo como a linha abaixo:<\/p>\n<p><code>[Warning] IP address '#.#.#.#' could not be resolved: Name or service not known<\/code><\/p>\n<p>Interessante saber exatamente o que cada evento adicionado ao log de erros do MySQL representa para que seu sistema continue rodando sem problemas de downtime e ter a possibilidade de ser mais proativo com os poss\u00edveis problemas que o MySQL e os seus bancos de dados possam apresentar no futuro.<\/p>\n<p>Esse foi um post curto, mais te\u00f3rico que pr\u00e1tico, mas, a boa not\u00edcia e que vou tentar voltar em breve!!<\/p>\n<p>Happy MySQL&#8217;ing!!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Desde o lan\u00e7amento da vers\u00e3o 5.5 do servidor de bancos de dados MySQL que eu venho verificando muitos problemas relacionados com a vari\u00e1vel de resolu\u00e7\u00e3o de nomes, skip-name-resolve. Para quem ainda n\u00e3o sabe ou est\u00e1 iniciando com o MySQL, toda vez que o servidor de bancos de dados recebe uma consulta, como por exemplo, aquela [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"http:\/\/wagnerbianchi.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/831"}],"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=831"}],"version-history":[{"count":1,"href":"http:\/\/wagnerbianchi.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/831\/revisions"}],"predecessor-version":[{"id":832,"href":"http:\/\/wagnerbianchi.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/831\/revisions\/832"}],"wp:attachment":[{"href":"http:\/\/wagnerbianchi.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=831"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/wagnerbianchi.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=831"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/wagnerbianchi.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=831"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}