行数150M、サイズ550GBなんていう一枚テーブルをinnodbで作ってしまいました。4TB HDD使ってるのでまだまだ溜め込めますが、こんな量のデータを1つのテーブルに入れることが何か間違っているような気がする。
こうなるとインデックス無しではまともにデータは取り出せませんので、まだテーブルが小さかった頃に数個作ってありました。で、恐れていた事態、インデックスの追加。幸いにもMySQL 5.6ではテーブルをロックせずにインデックスを追加・削除できる ようになったので、何日かかるかわからないけどcreate index文を実行。翌朝見ると異常終了orz
そういえば昨日の帰り際、MySQLのCPU使用率が10%前半に落ちてたな(コマンド開始時は30~50%)、メモリが足りないのかと思い、innodb_buffer_pool_size を2GB→6GBに増やして再挑戦。mysqldは順調に実メモリは消費しましたが、仮想メモリに手を出す様子はなし。
しばらく様子を見ていると、/の入っているHDD残量が少しずつ減っているのを発見。ですが前述の通り仮想メモリは増えてない。はて?
ネットで情報を探していると、たどり着いたのがこれ 。
tmpdirについて少し補足します。MySQLがtmpdirに作成した一時ファイルはlsなどのコマンドでは見ることができません。これはMySQLが一時ファイルを作成したあと、すぐに削除してしまうためです。 LinuxなどのOSでは、ファイルを削除してもそのファイルをオープンしているプロセスがある限り実際の削除は行われません。逆に言えば、こうしておくことでプロセス終了時に一時ファイルが自動的にクリーンアップされるというわけです。lsofコマンドであればMySQLが作成した一時ファイルを確認することができます。書かれている通りにlsofをやってみると
# lsof -p 2249 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME (省略) mysqld 2249 mysql 39u REG 0,39 5445255168 3534 /var/tmp/mysql.zUtW7u/ibDLGxdb (deleted)たすかに~。/var/tmpにディレクトリを作っていてサイズが増えていっているけど、lsで/var/tmp/mysql.zUtW7uを見ても空っぽ。増える速度はおおよそ20GB/日(画像参照)。/の容量からして昨晩使い果たして落ちたという理由は合点がいく。
応急策としてiSCSIサーバから800GB融通してもらって/に追加。btrfsなのでインデックス作成終わったら外そうと思ってますが、今考えたら追加800GB単独でフォーマットして/var/tmpにマウントした方が安全だったな…
そのほかの環境- CPU: Haswell Xeon 3.5GHz
- OS: OpenSUSE 13.2 (VMware ESXi 5.5上)
- DBMS: MySQL 5.6.17-2.1.12 (yastにてインストール)
- ファイルシステム: btrfs (OS用に10GB、MySQL用に4TB)
- VMのメモリ: 4GB→8GB
- MySQL 5.6における大量データロード時の考慮点 (SH2の日記)
- Optimizing MySQL Indexes (sitepoint)
- The InnoDB Buffer Pool (MySQL)
[2015/6/26 追記]/var/tmp増量後に再挑戦も翌朝失敗。忘れたころにやってくるOOM Killer 。topで見るとメモリを12GBほど要求しているらしい。swap増量、/proc/(mysqldのPID)/oom_adjに-17を書き込んで応戦、9時間後に3度目の正直で成功。
Comments