クエリ発行してたら「ERROR 1114 (HY000): The table 'tablename' is full」って怒られた話
なんでさ!
はい基本情報チェーック
利用しているデータベースは全体で 2Gbyte ちょっとあって、MySQL Cluster (7.2.17) で動いてる。is full って文句を言われた時に実行してたクエリはぼかすけどこんなん。
mysql> mysql> UPDATE tablename SET column1 = '' WHERE 〜〜〜 LIMIT 20000; ERROR 1114 (HY000): The table 'tablename' is full
特定の箇所を全部うめるとかいうあれ、二万件毎を処理してた。
原因はなんだ?
オンメモリデータベースなのと、直近の ndb_mgmd.log から「Datamemory Usage 80%」を超えてたので、あー容量たりねえのかな?と思って、API node の my.cnf をちょちょいと変更。
[root@apinode1 ~]# vi /etc/my.cnf #DataMemory=5G DataMemory=7G [root@apinode ~]# ndb_mgm ndb_mgm> all stop [root@ndbnode ~]# ndbd -n [root@apinode ~]# ndb_mgm ndb_mgm> all start
だいぶはしょってますが、DataMemory 増やしてクラスタ全体を再起動してます。これで DataMemory 増えたし平気でしょ!
mysql> UPDATE tablename SET column1 = '' WHERE 〜〜〜 LIMIT 20000; ERROR 1114 (HY000): The table 'tablename' is full
ゴボボーッ!ナンデ!!
ということで、全ての稼働中ノードのキャッシュメモリを強制的に解放して、メモリに空きを作って見ます(以下は実際の作業結果です)。
[root@ndbnode ~]# free -m total used free shared buffers cached Mem: 11912 10151 1760 0 286 2926 -/+ buffers/cache: 6938 4974 Swap: 12079 0 12079 [root@ndbnode ~]# sync [root@ndbnode ~]# echo 3 > /proc/sys/vm/drop_caches [root@ndbnode ~]# free -m total used free shared buffers cached Mem: 11912 6901 5011 0 2 24 -/+ buffers/cache: 6874 5038 Swap: 12079 0 12079
apinode でも別に実行してありますが、 cached が解放されて良い感じですね?では、再度試してみましょう!
mysql> mysql> UPDATE tablename SET column1 = '' WHERE 〜〜〜 LIMIT 20000; ERROR 1114 (HY000): The table 'tablename' is full
ほんぎゃあ!
アイエエエ、助けて
ずっと「mysql cluster full」「助けて」「マッポー」など訳の分からないワードでググっておりましたが、別に mysql cluster に限定しなくてよかったんですね。なんせクエリを実行するのは MySQL そのものなんすから。
MySQL Reference Manual for version 3.21.31. - �����Ȥ褯���륨�顼
ワッザ!という訳で tmp_table_size を確認してみましょう。
mysql> SHOW VARIABLES LIKE 'tmp_table_size'; +----------------+-----------+ | Variable_name | Value | +----------------+-----------+ | tmp_table_size | 536870912 | +----------------+-----------+ 1 row in set (0.00 sec)
アッ、アイエエエ?!
[root@apinode1 ~]# less /etc/my.cnf tmp_table_size=512M
オッヴェ!こんだけ確保してても駄目なの?決断的に増やしますよ。
[root@apinode1 ~]# less /etc/my.cnf #tmp_table_size=512M tmp_table_size=768M mysql> SHOW VARIABLES LIKE 'tmp_table_size'; +----------------+-----------+ | Variable_name | Value | +----------------+-----------+ | tmp_table_size | 805306368 | +----------------+-----------+ 1 row in set (0.00 sec)
どうよ!
mysql> UPDATE tablename SET column1 = '' WHERE 〜〜〜 LIMIT 20000; おk mysql> UPDATE tablename SET column1 = '' WHERE 〜〜〜 LIMIT 20000; おk mysql> UPDATE tablename SET column1 = '' WHERE 〜〜〜 LIMIT 20000; おk mysql> UPDATE tablename SET column1 = '' WHERE 〜〜〜 LIMIT 20000; ERROR 1114 (HY000): The table 'tablename' is full
ほんぎゃあ!
わかったこと
そら更新する箇所によってデータが入ってたり入ってなかったりで、結局一律同じ LIMIT で回すと tmp_table_size の制限を超えてしまう箇所があるわな、というオチでした。書き込むテーブル自体はまだまだ書き込める状況でも、一度のクエリ実行結果で tmp_table_size を超えると何故か「The table 'tablename' is full」という表示になる ( tmp or heap table is full とか出てくれればわかりやすかったね )。
という訳で、一度に実行する数を少なくすることで回避しました。
mysql> UPDATE tablename SET column1 = '' WHERE 〜〜〜 LIMIT 5000; おk
tmp_table_size をいじらなくても最初からこうしてれば解決した気もしますねこれ……。