大量のデータを保持するMySQLデータベースを持っています(100-200GB-一連の科学的測定値)。データの大部分は1つのテーブルSample
に格納されます。ここで、データベースのスレーブレプリカを作成しています。プロセス中に_innodb_file_per_table
_の利点を活用したいと思いました。したがって、スレーブ構成で_innodb_file_per_table
_を設定し、データベースのダンプをインポートしました。驚いたことに、それは失敗しました
5602行目のエラー1114(HY000):テーブル「Sample」がいっぱいです
ファイル_Sample.ibd
_は現在約93GBであり、パーティションに600GB以上の空き容量があるため、ディスクの空き容量の問題ではありません。どちらのファイルシステムの制限にも達していないようです(私はext4を使用しています)。
何が原因なのか、何を調べればよいのか、どんなアイデアにも感謝します。
pdate:mysql Ver 14.14 Distrib 5.1.66, for debian-linux-gnu (x86_64)
を使用しています。
_SELECT @@datadir; -- returns `/home/var/lib/mysql/`
SHOW VARIABLES LIKE '%innodb_data_file_path%'; -- ibdata1:10M:autoextend
df -h /home/var/lib/mysql/
768G 31G 699G 5% /home
_
ext4
を使用しているとのことですが、ファイルサイズの上限は16TBです。したがって、Sample.ibd
がいっぱいであってはなりません。
あなたのinnodb_data_file_path
はibdata1:10M:autoextend
だと言いました。したがって、ibdata1ファイル自体には、OS以外のサイズに上限はありません。
なぜこのメッセージが出てくるのですか?メッセージが「ディスク...がいっぱいです」ではなく、「テーブル...がいっぱいです」であることに注意してください。 このテーブルの完全な状態は、論理的な観点からです。 InnoDBについて考えてみてください。どんな相互作用が起こっていますか?
私の推測では、InnoDBは93GBのデータを単一のトランザクションとしてロードしようとしています。 Table is Full
メッセージはどこから発信されますか?私はibdata1を、その物理的なサイズ(既に除外されている)ではなく、どのトランザクション制限に達しているかという観点で調べます。
innodb_file_per_table が有効になっていて、新しいデータをMySQLにロードする場合、ibdata1内には何がありますか?
ibdata1
の図解をご覧ください私の疑いは、元に戻すログややり直しログのせいだと私に言います。
これらのログとは何ですか? The Book によると
第10章:「ストレージエンジン」203ページパラグラフ3,4では、次のように述べています。
InnoDBエンジンは、元に戻すログとやり直しログの2種類のログを保持します。 undo logの目的は、トランザクションをロールバックすることと、それを必要とするトランザクション分離レベルで実行されているクエリの古いバージョンのデータを表示することです。元に戻すログを処理するコードは、storage/innobase/buf/log/log0log.cにあります。
redo logの目的は、クラッシュリカバリで使用される情報を保存することです。これにより、回復プロセスは、クラッシュの前に完了したかどうかに関係なく、トランザクションを再実行できます。これらのトランザクションを再実行した後、データベースは一貫した状態になります。 REDOログを処理するコードは、storage/innobase/log/log0recv.cにあります。
1023個の元に戻すログがあります ibdata1内(ロールバックセグメントと元に戻すスペースを参照) 。元に戻すログはリロード前と同じようにデータのコピーを保持するため、すべての1023元に戻すログが上限に達しています。別の見方をすると、すべての1023元に戻すログは、Sample
テーブルをロードする1つのトランザクション専用である可能性があります。
あなたはおそらく「空のSample
テーブルをロードしています」と言っているでしょう。元に戻すログはどのように関係していますか? Sample
テーブルに93GBのデータがロードされる前は、テーブルは空でした。存在しなかったすべての行を表すには、元に戻すログのハウスクリーニングスペースを使用する必要があります。 ibdata1
に注がれるデータの量を考えると、1023の取り消しログがいっぱいになるのは簡単なことです。私はこれを疑う最初の人ではありません:
MySQL 4.1ドキュメントから、Posted by Chris Calender on September 4 2009 4:25pm
に注意してください:
5.0(5.0.85より前)および5.1(-5.1.38より前)では、InnoDBがアンドゥスロットを使い果たすと、InnoDBテーブルの「テーブルがいっぱいです」というエラーを受け取る可能性があることに注意してください(バグ#18828)。
MySQL 5.0のバグレポートは次のとおりです。 http://bugs.mysql.com/bug.php?id=18828
Sample
テーブルのmysqldumpを作成するときは、 -no-autocommit を使用してください
mysqldump --no-autocommit ... mydb Sample > Sample.sql
これは、INSERT
の後に明示的なCOMMIT;
を置きます。次に、テーブルをリロードします。
これが機能しない場合(これは好きではありません)、これを行います
mysqldump --no-autocommit --skip-extended-insert ... mydb Sample > Sample.sql
これにより、各INSERTは1行だけになります。 mysqldumpははるかに大きく(10倍以上)、リロードに10〜100倍の時間がかかる可能性があります。
どちらの場合も、これにより、元に戻すログが氾濫するのを防ぐことができます。
試してみる !!!
InnoDBシステムテーブル(別名ibdata1)がファイルサイズの制限に達し、ログの取り消しを使用できない場合は、別のシステムテーブルスペース(ibdata2)を追加するだけで済みます。
ちょうど2日前にこの状況に遭遇しました。以前の投稿を自分のやったことで更新しました:参照 データベースの設計-テーブルサイズの制限という頭痛の種を避けるために複数のデータベースを作成する
基本的に、新しいシステムテーブルスペースファイルに対応するには、 innodb_data_file_path を変更する必要があります。方法を説明しましょう:
ディスク(ext3)では、クライアントのサーバーには次のものがありました。
[root@l*****]# ls -l ibd*
-rw-rw---- 1 s-em7-mysql s-em7-mysql 362807296 Jun 2 00:15 ibdata1
-rw-rw---- 1 s-em7-mysql s-em7-mysql 2196875759616 Jun 2 00:15 ibdata2
設定は
innodb_data_file_path=ibdata1:346M;ibdata2:500M:autoextend:max:10240000M
ibdata2
が2145386484M
である2196875759616に成長したことに注意してください。
ibdata2
のファイルサイズをinnodb_data_file_pathに埋め込み、ibdata3
を追加する必要がありました
innodb_data_file_path=ibdata1:346M;ibdata2:2196875759616;ibdata3:10M:autoextend
Mysqldを再起動すると、うまくいきました。
[root@l*****]# ls -l ibd*
-rw-rw---- 1 s-em7-mysql s-em7-mysql 362807296 Jun 3 17:02 ibdata1
-rw-rw---- 1 s-em7-mysql s-em7-mysql 2196875759616 Jun 3 17:02 ibdata2
-rw-rw---- 1 s-em7-mysql s-em7-mysql 32315015168 Jun 3 17:02 ibdata3
40時間後に、ibdata3
は31Gに成長しました。 MySQLが再び機能しました。
私も同じ問題を抱えていて、1つのことを行っただけでうまくいきました。
innodb_data_file_path
構成ファイルのmy.cnf
の最大サイズが小さすぎるようです。以下のコードを変更するだけです-
innodb_data_file_path = ibdata1:10M:autoextend:max:512M
重要な注意すべてのInnoDB
テーブルで、512MB
を超えるデータをホストすることはできません。
innodb_file_per_table
を使用して、テーブルごとのinnodb-スキームに切り替えることもできます。