max_join_sizeパラメータに関するメッセージについて

前回(MySQL table_cacheの設定に関して)に引き続き、MySQLネタ。自宅システム内の32bit Linuxプラットフォーム上のMySQLで、mysqld_safeのログに気になるメッセージ。今回はこの件について考える。ポイントとなるパラメータはmax_join_size。これは、一回の結合クエリで保持できる最大データサイズを指定するパラメータである。


[Warning] option 'max_join_size': unsigned value 18446744073709551615 adjusted to 4294967295

メッセージが出る理由の考察

プログラムを書く方ならおやっと思うかもしれないが、「4294967295」という数値は、unsigned int(32)の上限値(4G)で、「18446744073709551615」は、unsigned int(64) (一般的に u long long)の上限値(16E、4G*4G)となっている。私がこのメッセージを確認した環境はCentOS5 32bit上のMySQL5.0.70環境だが、以前(MySQL 5.0.45の頃)は同じ設定でもこのメッセージは出ていなかったように記憶している。おそらく、どこかのバージョンアップの際に、ソースコード上での指定が、uint_32からuint_64に変わったのではないかと思われる。

i386(i686)ベースのアーキテクチャでは、事実上4G以上のデータをメモリに確保することが出来ないため、「最大サイズを4GBに制限しました」という警告がmysqld起動時に出るようになったんではないかと推測される(swapがどうとかではなく、そのプロセスが保持できるポインタサイズが32bitなので、4GB以上の領域にアクセス出来ない)。

対策を考える

<64bit環境の場合>

根本的に64bit環境では発生しない問題のはず・・・ということで、実際にCentOS 5.3 64bitを導入したVMWareゲストマシンにメモリを10GB割り当て、MySQLを起動してみた。結果 mysqld/mysqld_safeともに、ログに問題のメッセージが出ることはなかった(当然といえば当然)。これが根本的な解決策。実メモリを4GB以上搭載しない場合にも問題ないのかを確認するためVMの割り当てメモリを1GBまで減らし試したところ、搭載メモリには関らずメッセージが出ないことを確認できた。

<32bit環境の場合>

32bit環境では max_join_size の値が4294967295(=4GB)を超えられないことを諦め、my.cnfの中で明示的にmax_join_sizeの値を4GB以下の値として1G(=1073741824バイト)を記述してみた。が、結果的にはmysqld_safeのログに問題のメッセージが出続けていたorz mysqld起動後にshow variablesで確認したところ、


$ mysql -s -uroot -p -e "show variables like 'max_join_size'"
Enter password:
Variable_name Value
max_join_size 1073741824
これだけ見ると、my.cnfに設定した値は正常に反映されており、mysqld_safeに記録された値 4294967295(4GB)にはなっていない。挙動を確認するに、どうやらこれは実際にmysqldのメモリ上に展開された変数値が変更されるというわけではなく、あくまで「警告として」ログに出力されているもののようだ。

<結論として>

今回の問題はmysqldだけの問題ではなく、kernelやglibcの制限も絡んでくる問題。64bit環境であれば実際の搭載メモリサイズに関らず問題のメッセージは出ない。ただ32bit環境の場合(basearchがi386系の時)は、これは出るものなんだと思って諦めることにした。