エラーメッセージに騙されないでくださいThe table 'my_table' is full
。このまれなシナリオは、ディスクスペースとはまったく関係ありません。このテーブルフルの状態は、InnoDBの内部配管に関係しています。
まず、このInnoDBアーキテクチャの図を見てください。
システムテーブルスペース(ファイルibdata)には、ロールバックセグメントごとに128のロールバックセグメントと1023のロールバックスロットしかないことに注意してください。これにより、トランザクションのロールバック容量のサイズが制限されます。つまり、1つのロールバックセグメントがトランザクションをサポートするために1023を超えるスロットを必要とする場合、トランザクションはそのtable is full
条件にヒットします。
ニュージャージー州のレストランRed Lobsterについて考えてみましょう。それは200人の容量があるかもしれません。レストランが満員の場合、列に並ぶ人が外に出ることがあります。行列ができなくなった場合、店が満員になって帰ってしまう可能性があります。明らかに、解決策はニュージャージーを大きくする(またはディスク容量を増やす)ことではありません。解決策は、Red Lobsterレストランを大きくすることです。そうすれば、収容人数を240人まで増やすことができます。それでも、240人を超える人がレッドロブスターに来ることを決めた場合、外に列ができることがあります。
例を挙げれば、2TBのシステムテーブルスペースを持つクライアントがあり、innodb_file_per_tableが無効になっています。(ibdata1の346G、ibdata2のリセット)。このクエリを実行しました
SELECT SUM(data_length+index+length) InnoDBDataIndexSpace
FROM information_schema.tables WHERE engine='InnoDB';
次に、ibdata1とibdata2のファイルサイズの合計からInnoDBDataIndexSpaceを引きました。私は私に衝撃を与えた2つのものを得ました
- システムテーブルスペース内に106GB残っていました。
- 私はこれと同じ
Table is Full
状態になりました
これは、106GBがInnoDBの内部配管に使用されていたことを意味します。当時、クライアントはext3を使用していました。
私にとっての解決策は、ibdata3を追加することでした。私はこれを以前の投稿で説明しました「innodb_file_per_table」で「テーブルがいっぱいです」を解決する方法は?
私は他の投稿でもこれについて議論しました
この状態は、innodb_file_per_tableが有効になっていても発生する可能性があることに注意してください。どうやって?ロールバックと元に戻すログは、制御されていないスパイクの原因であり、ibdata1の増加です。
あなたの実際の質問
インデックスをテーブルに追加してを取得しているTable is Full
ため、テーブルは巨大である必要があり、単一のロールバックセグメント内に収まりません。次のことを行う必要があります。
ステップ01
データをダンプファイルに取得する
mysqldump --no-create-info mydb mytable > table_data.sql
ステップ02
MySQLにログインしてこれを実行します
USE mydb
CREATE TABLE mytable_new LIKE mytable;
ALTER TABLE mytable_new ADD INDEX ... ;
ALTER TABLE mytable RENAME mytable_old;
ALTER TABLE mytable_new RENAME mytable;
ステップ03
データを含む追加のインデックスをテーブルにロードします
mysql -Dmydb < table_data.sql
それで全部です。
問題は、ALTER TABLEが巨大なテーブルのすべての行を1つのトランザクションとして挿入しようとすることです。mysqldumpを使用すると、単一のトランザクションのすべての行ではなく、一度に数千行のデータがテーブル(現在は新しいインデックス)に挿入されます。
心配しないでくださいwhat if this doesn't work?
。元のテーブルはmytable_old
、何かの場合に名前が付けられます。バックアップとして使用できます。新しいテーブルが機能することがわかったら、バックアップを削除できます。
試してみる !!!
UPDATE 2014-06-16 11:13 EDT
より大きなデータのダンプが心配な場合は、gzipしてください。
同じ手順を実行できますが、次のようになります
ステップ01
データをダンプファイルに取得する
mysqldump --no-create-info mydb mytable | gzip > table_data.sql.gz
ステップ02
MySQLにログインしてこれを実行します
USE mydb
CREATE TABLE mytable_new LIKE mytable;
ALTER TABLE mytable_new ADD INDEX ... ;
ALTER TABLE mytable RENAME mytable_old;
ALTER TABLE mytable_new RENAME mytable;
ステップ03
データを含む追加のインデックスをテーブルにロードします
gzip -d < table_data.sql.gz | mysql -Dmydb
または
gunzip < table_data.sql.gz | mysql -Dmydb
UPDATE 2014-06-16 12:55 EDT
私はこの問題に関して別の側面を考えました。
DMLではなくDDLを実行しているため、これがInnoDBの内部配管ではない可能性があります。以来DDLは、InnoDBのためにロールバックすることはできません、問題は、外部の配管にする必要があります。この外部配管はどこで詰まっていますか?OSの一時フォルダーが疑われます。どうして?
140616 13:04:33 InnoDB: Error: Write to file (merge) failed at offset 3 1940914176.
InnoDB: 1048576 bytes should have been written, only 970752 were written.
InnoDB: Operating system error number 0.
InnoDB: Check that your OS and file system support files of this size.
InnoDB: Check also that the disk is not full or a disk quota exceeded.
InnoDB: Error number 0 means 'Success'.
InnoDB: Some operating system error numbers are described at
InnoDB: http://dev.mysql.com/doc/refman/5.5/en/operating-system-error-codes.html
140616 13:04:33 [ERROR] /usr/libexec/mysqld: The table 'my_table' is full
を参照してくださいdisk quota exceeded
。このディスククォータはどこに課されていますか?
このクエリを実行する
SHOW GLOBAL VARIABLES LIKE 'tmpdir';
あなたはそれだと言った /var/lib/mysqltmp
これをOSで実行します
df -h /var/lib/mysqltmp
なんとかして空き容量/var/lib/mysqltmp
が足りなくなったようですが、結局のところ、14Gしか空き容量がありません。(インデックスを作成するための)DDLの目には、ibdata1ファイルではなく、tmpdir
場所でロールバックが発生しました。/var/lib/mysqltmp
がどこにもマウントされていない場合、一時データはルートパーティションに書き込まれています。/var/lib/mysqltmp
がどこかにマウントされている場合、そのマウントは行データで埋められています。どちらの場合も、DDLを完了するための十分なスペースがありません。
ここには2つのオプションがあります
オプション1
大きなディスク(おそらく100 GB以上)を作成し、/var/lib/mysqltmp
その大きなディスクにマウントすることもできます。
オプション#2
私の3ステップの提案は、ディスクスペースが限られている場合でも機能します。
解説
あなたが投稿したエラーメッセージが言うのは残念です
InnoDB: Operating system error number 0.
InnoDB: Error number 0 means 'Success'.
つまり、OSは問題ありません。また、この状況に関連するエラー番号はありません。
もう1つ知っておくべきことがあります。MySQLドキュメントによると、InnoDBの高速インデックス作成はまだディスクに保存されています。
インデックスの作成中、ファイルは一時ディレクトリ(Unixでは$ TMPDIR、Windowsでは%TEMP%、または--tmpdir構成変数の値)に書き込まれます。各一時ファイルは、新しいインデックスを構成する1つの列を保持するのに十分な大きさで、最終的なインデックスにマージされるとすぐに削除されます。
MySQLの制限により、TEMPORARY TABLEにインデックスを作成するときに「高速インデックス作成」を使用するのではなく、テーブルがコピーされます。これはMySQLバグ#39833として報告されています。
UPDATE 2014-06-16 13:58 EDT
[mysqld]
datadir = /mnt/cbsvolume1/var/lib/mysql
tmpdir = /mnt/cbsvolume1/var/lib/mysql
/mnt/cbsvolume1/var/lib/mysql
100G以上の空き容量があることを確認してください