MySQLのハマりどころ
前回に引き続き、テーマはMySQLです。
パラメータのチューニングは、
「MySQL チューニング」で検索すれば、山ほど出てくるので、
そちらに譲るとして、もっと初歩的なところに触れたいと思います。
(特に、http://dsas.blog.klab.org/archives/50860867.html には私も大変お世話になりました)
skip-resolve-nameは無効にしよう
まずは、my.cnfのパラメータ「skip-name-resolve」についてです。
以下は、Donutsで使っている標準的な設定で、一番下の行にあります。
[mysqld] datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock user=mysql log-slow-queries long_query_time=1 #log-queries-not-using-indexes #log=/var/lib/mysql/query.log # server-id=40 # log-bin=/var/lib/mysql_log/binlog # log-slave-updates # expire_logs_days = 1 max_connections=100 thread_cache_size=100 key_buffer_size=64M myisam_sort_buffer_size=1M sort_buffer_size=1M read_buffer_size=1M innodb_file_per_table innodb_log_file_size=2000M innodb_log_buffer_size=32M innodb_buffer_pool_size=4000M innodb_additional_mem_pool_size=20M innodb_flush_log_at_trx_commit=0 innodb_support_xa=0 #innodb_flush_method=O_DIRECT skip-innodb_doublewrite skip-innodb_checksums skip-name-resolve
以前から、MySQLへの新規接続が時々、遅いWebサーバーがあり、
疑問に思っていたところ、状況がわかってきました。
DBサーバーのhostsファイルに、
IPアドレスが書かれているWebサーバーは接続が早く、
IPアドレスが書かれていないWebサーバーは接続が遅かったのです。
そして、根本的な原因は、skip-resolve-nameを設定していたことでした。
skip-resolve-nameは、接続を受けた際に、
認証の目的でクライアントのIPアドレスを逆引きする機能です。
接続が遅かった原因は、hostsファイルにIPアドレスが書かれていなかったため、
DNSサーバーで名前解決をしようとしていたことによるものでした。
詳細はこちら: http://dev.mysql.com/doc/refman/5.5/en/dns.html
あまりに基本的すぎるためか、このことについて書いてある情報源が少ないです。
しかし、大量の接続を行う場合は、これを無効にしないと話になりません。
自前でDNSサーバーを運用していれば、まだ良いのですが、
プロバイダのDNSサーバーを使用している場合は、大迷惑。
最終的にはアクセスを禁止されて、「なぜか、DBサーバーに接続できない」事件に発展します。
なぜ、このような機能がデフォルトで有効なのか理解に苦しみます。
MySQL5.0で、無意味な文言が記録される
クエリのチューニングには欠かせない slowqueryのファイルに時々、SQL文が記録されず、
# administrator command: Prepare Execute;
という文言だけが記録されることがあるようです。
MySQL 5.0 だけで 5.5 では起きていないので、早くバージョンアップする必要があるということかもしれませんが。
また、他にもlong_query_time に1秒以下を指定できなかったりもするので、やはり、バージョンアップしたいところです。
(Zend_Db_Profilerを使用したプロファイリングについては次回紹介します)。
ちなみに、Donutsでは、最初に使用し始めたMySQLのバージョンが、CentOS5のデフォルトの5.0.77 であったため、
いまだに5.0.77を使用しているDBサーバーがあります。
MySQL5.5で、InnoDBがtmpfs上で動作しない
ところが、MySQL5.5に移行することに踏み切れない理由がありました。
tmpfs上でInnoDBを動かそうとすると、MySQLが落ちてしまうのです。
http://bugs.mysql.com/bug.php?id=58421
tmpfs にはasynch I/Oが無いのに、asynch I/Oでアクセスしようとして、
Kernelに怒られ、落ちてしまうようです。
1年近く前に、BugDBに挙がっているので、バグフィックスが待ち遠しいところです。
MySQL5.5では、unsingedカラムの更新に注意
MySQL 5.5では、unsingedを指定してあるカラムを更新するupdate 文で、
式の評価途中、負になる場合、エラーとなってしまうようです。
(以下の例では、「col1 - 2」の部分が負になります。)
mysql> create table testtable2 (col1 int unsigned); mysql> insert into testtable2 (col1) values (1); mysql> update testtable2 set col1=col1-2+10; ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(`t`.`testtable2`.`col1` - 2)'
5.0 では何事もなく更新されるのですが…
式の評価途中、負になる場合は、明示的にキャストしてやる必要があるようです。
mysql> update testtable2 set col1=cast(col1 as signed)-2+10; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from testtable2; +------+ | col1 | +------+ | 9 | +------+ 1 row in set (0.00 sec)