MySQLでibdata1ファイルを縮小/パージする方法


561

Rで統計を実行するための「クエリツール」としてlocalhostでMySQLを使用しています。つまり、Rスクリプトを実行するたびに、新しいデータベースを作成し(A)、新しいテーブルを作成し(B)、データをBにインポートします。 、クエリを送信して必要なものを取得し、BをドロップしてAをドロップします。

私にとっては問題なく動作していますが、ibdataファイルのサイズが急速に増加していることを認識しています。MySQLには何も保存していませんが、ibdata1ファイルはすでに100 MBを超えています。

設定に多かれ少なかれデフォルトのMySQL設定を使用していますが、一定期間後にibdata1ファイルを自動的に縮小/パージする方法はありますか?


回答:


778

これibdata1は、MySQLの特に煩わしい機能ではありません。ibdata1すべてのデータベースを削除し、ファイルを削除してダンプをリロードしない限り、ファイルを実際に縮小することはできません。

ただし、インデックスを含む各テーブルが個別のファイルとして保存されるようにMySQLを設定できます。そのようibdata1にして、それほど大きくはなりません。Bill Karwinのコメントによると、これはMySQLのバージョン5.6.6以降、デフォルトで有効になっています。

少し前のことです。ただし、サーバーをセットアップしてテーブルごとに個別のファイルを使用my.cnfするには、これを有効にするために変更する必要があります。

[mysqld]
innodb_file_per_table=1

http://dev.mysql.com/doc/refman/5.5/en/innodb-multiple-tablespaces.html

スペースを取り戻したいので、ibdata1実際にはファイルを削除する必要があります。

  1. やるmysqldumpすべてのデータベース、プロシージャ、トリガなどの除くmysqlperformance_schemaデータベース
  2. 上記の2つのデータベースを除くすべてのデータベース削除します
  3. mysqlを停止する
  4. 削除ibdata1ib_logファイル
  5. mysqlを起動
  6. ダンプから復元

手順5でMySQLを起動するibdata1と、and ib_logファイルが再作成されます。

これで準備万端です。分析用に新しいデータベースを作成すると、テーブルはでibd*はなく別のファイルに配置されますibdata1。通常はすぐにデータベースをibd*削除するので、ファイルは削除されます。

http://dev.mysql.com/doc/refman/5.1/en/drop-database.html

おそらくこれを見たことがあるでしょう:http :
//bugs.mysql.com/bug.php?id=1341

コマンドを使用するALTER TABLE <tablename> ENGINE=innodbOPTIMIZE TABLE <tablename>、ibdata1からデータとインデックスページを抽出してファイルを分離できます。ただし、上記の手順を実行しない限り、ibdata1は縮小されません。

についてはinformation_schema、ドロップする必要はありません。実際には、テーブルではなく、読み取り専用のビューの集まりにすぎません。そして、それらに関連付けられているファイルはなく、データベースディレクトリさえありません。informations_schemaメモリDBエンジンを使用しているとのmysqldの停止/再起動時に滴下して再生されます。https://dev.mysql.com/doc/refman/5.7/en/information-schema.htmlを参照してください


16
@JordanMagnuson information_schemaを削除する必要はありません。実際には、テーブルではなく、読み取り専用のビューの集まりにすぎません。そして、それらに関連付けられているファイルはありません。データベース用のディレクトリさえありません。informations_schemaはメモリdb-engineを使用しており、mysqldの停止/再起動時に削除および再生成されます。dev.mysql.com/doc/refman/5.5/en/information-schema.htmlを参照してください。performance_schemaについては、自分ではそのスキーマを使用していません。
ジョンP

4
これが最近のものかどうかはわかりませんが、innodb_file_per_tableオプションを有効にすると、「ALTER TABLE <tablename> ENGINE = InnoDB」を実行するだけで(すでにInnoDBであっても)、テーブルを個々のファイルに移動できます。データベースなどを削除する必要はありません。
CR。

3
+1 FWIW、MySQL 5.6ではinnodb_file_per_tableデフォルトで有効になっています。
Bill Karwin 2013年

3
はい、ibdata1は他のファイルと共に存在することが期待されています。ibdata1ファイルには、テーブル、元に戻すログ、およびバッファに関するメタデータが引き続き保持されます。
John P

1
ibdata1ファイルが原因でサーバーのスペースが足りなくなったため、データベースをダンプすることもできません。/ var / lib / mysql(「mysql」、「ibdata1」、「ib_logfile0」、「ib_logfile1」を除く)にファイルを移動し、手順に従うだけでも同じでしょうか?stackoverflow.com/questions/2482491/…を
Sophivorus 14年

47

追加ジョン・Pの答え

Linuxシステムの場合、手順1〜6は次のコマンドで実行できます。

  1. mysqldump -u [username] -p[root_password] [database_name] > dumpfilename.sql
  2. DROP DATABASE [database_name];
  3. sudo /etc/init.d/mysqld stop
  4. sudo rm /var/lib/mysql/ibdata1
    sudo rm /var/lib/mysql/ib_logfile (と命名することができる任意の他のib_logfile年代を削除するib_logfile0ib_logfile1など...)
  5. sudo /etc/init.d/mysqld start
  6. create database [database_name];
  7. mysql -u [username]-p[root_password] [database_name] < dumpfilename.sql

警告:このmysqlインスタンスに他のデータベースがある場合、これらの指示により他のデータベースが失われます。保持したいすべてのデータベースをカバーするようにステップ1、2、6、7が変更されていることを確認してください。


6
InnoDBテーブルを持つデータベースごとに1、2、6を繰り返す必要があります。
ローンの侯爵2014年

4
#5と#6の間にはさらにいくつかのステップが必要です。データベースを再作成し、権限を再度割り当てる必要があります。mysqlクライアントコマンドプロンプトcreate database database_name;からgrant all privileges on database_name.* to 'username'@'localhost' identified by 'password';
フレッド14年

1
@fredこれを行うときに特権を付与する必要はありませんでした。おそらく同じ名前でデータベースを再作成したためでしょうか?
crmpicco

2
Password:プロンプトでパスワードを入力するには(これはより安全な方法です)、-p実際のパスワードなしで入力します。
ADTC、2017年

mysqldumpに指示しない限り、トリガー、イベント、ルーチン/関数はダンプされません。--triggers、-events、および--routinesを追加します(データベースに含まれている場合)。また、--all-databasesを指定してダンプするだけで、すべてのデータベースを1つずつではなく一度にダンプできます。
Friek

34

innodbテーブルを削除しても、MySQLはibdataファイル内のスペースを解放しないため、成長し続けます。これらのファイルはほとんど縮小しません。

既存のibdataファイルを縮小する方法:

http://dev.mysql.com/doc/refman/5.5/en/innodb-resize-system-tablespace.html

これをスクリプト化して、一定期間後に実行するようにスクリプトをスケジュールすることができますが、上記の設定では、複数のテーブルスペースの方が簡単な解決策のようです。

構成オプションを使用すると、innodb_file_per_table複数のテーブルスペースが作成されます。つまり、MySQLは1つの共有ファイルではなく、テーブルごとに個別のファイルを作成します。これらの個別のファイルはデータベースのディレクトリに保存され、このデータベースを削除すると削除されます。これにより、ケースでibdataファイルを縮小/パージする必要がなくなります。

複数のテーブルスペースの詳細:

http://dev.mysql.com/doc/refman/5.5/en/innodb-multiple-tablespaces.html


最初のリンク壊れて、私は見つけることができる最も近いもの:dev.mysql.com/doc/refman/5.5/en/...
BlackICEは

14

MySQLテーブル(の一部)にInnoDBストレージエンジンを使用している場合、おそらくデフォルトの構成で問題に遭遇したことでしょう。MySQLのデータディレクトリ(Debian / Ubuntu内の/ var / lib / mysql)に「ibdata1」というファイルがあります。MySQLインスタンスのほとんどすべてのInnoDBデータ(トランザクションログではない)を保持し、非常に大きくなる可能性があります。デフォルトでは、このファイルの初期サイズは10Mbで、自動的に拡張されます。残念ながら、設計上、InnoDBデータファイルは圧縮できません。そのため、DELETE、TRUNCATE、DROPなどは、ファイルが使用したスペースを再利用しません。

私はあなたがそこに良い説明と解決策を見つけることができると思います:

http://vdachev.net/2007/02/22/mysql-reducing-ibdata1/


11

承認された回答の手順をbashですばやくスクリプト化しました。

#!/usr/bin/env bash
DATABASES="$(mysql -e 'show databases \G' | grep "^Database" | grep -v '^Database: mysql$\|^Database: binlog$\|^Database: performance_schema\|^Database: information_schema' | sed 's/^Database: //g')"
mysqldump --databases $DATABASES -r alldatabases.sql && echo "$DATABASES" | while read -r DB; do
    mysql -e "drop database \`$DB\`"
done && \
    /etc/init.d/mysql stop && \
    find /var/lib/mysql -maxdepth 1 -type f \( -name 'ibdata1' -or -name 'ib_logfile*' \) -delete && \
    /etc/init.d/mysql start && \
    mysql < alldatabases.sql && \
    rm -f alldatabases.sql

名前を付けて保存しpurge_binlogs.shて実行しrootます。

除くmysqlinformation_schemaperformance_schema(およびbinlogディレクトリ)。

管理者の資格情報が/root/.my.cnfあり、データベースがデフォルトの/var/lib/mysqlディレクトリにあると仮定します。

このスクリプトの実行後にバイナリログを消去して、次のコマンドでディスク容量を増やすこともできます。

PURGE BINARY LOGS BEFORE CURRENT_TIMESTAMP;

まだ理由はわかりませんが、今日、いくつかのInnoDBテーブルが同様のプロセス中に破損したためalldatabases.sql、すべてのテーブルが正常かどうかを再確認する前に削除しませんでした。いくつかの改善点についてはinnodb_fast_shutdown=0、シャットダウン前に設定、autocommit=0SQLファイルをインポートする前にCOMMIT設定autocommit=1、SQLファイルをインポートした後に実行および設定、mysqlcheck --all-databasesバックアップを削除する前に使用します。
ビクター

6

MySQLの空き領域を監視することが目標であり、MySQLを停止してibdataファイルを圧縮できない場合は、テーブルステータスコマンドを使用して取得します。例:

MySQL> 5.1.24:

mysqlshow --status myInnodbDatabase myTable | awk '{print $20}'

MySQL <5.1.24:

mysqlshow --status myInnodbDatabase myTable | awk '{print $35}'

次に、この値をibdataファイルと比較します。

du -b ibdata1

ソース:http : //dev.mysql.com/doc/refman/5.1/en/show-table-status.html


4

mysql-serverの新しいバージョンでは、上記のレシピは「mysql」データベースを破壊します。古いバージョンでは動作します。新しい一部のテーブルでは、テーブルタイプINNODBに切り替わります。これにより、テーブルが損傷します。最も簡単な方法は次のとおりです。

  • すべてのデータベースをダンプする
  • mysql-serverをアンインストールします。
  • 残ったmy.cnfを追加します。
    [mysqld]
    innodb_file_per_table=1
  • / var / lib / mysqlのすべてを消去します
  • mysql-serverをインストールする
  • ユーザーとデータベースを復元する

1

すでに述べたように、ibdata1を縮小することはできません(そのためには、ダンプして再構築する必要があります)が、実際にそうする必要がないこともよくあります。

自動拡張(おそらく最も一般的なサイズ設定)を使用すると、ibdata1はストレージを事前に割り当て、ストレージがいっぱいになるたびに増大します。スペースがすでに割り当てられているため、書き込みが速くなります。

データを削除してもデータは縮小されませんが、ファイル内のスペースは未使用としてマークされます。新しいデータを挿入すると、ファイルをさらに大きくする前に、ファイル内の空のスペースが再利用されます。

したがって、実際にそのデータが必要な場合にのみ、成長し続けます。別のアプリケーション用のスペースが実際に必要でない限り、おそらくそれを縮小する理由はありません。


66
あなたはスペースを解放する必要性を少し軽視しすぎていると思います。
1

2
60Gigソリッドステートパーティションがあります。4ギガ以上のデータベースを使用しているため、スペースが足りなくなりました。私はmysqlをすぐに別のパーティションに移動することを考えていますが、この質問とその回答が当面の間私に役立ちます
NullVoxPopuli

3
この回答をありがとう、それはとても役に立ちます。レガシーデータからいくつかのテーブルを削除しました...ディスクのサイズがすぐに再び大きくなることはないことを知っておくのは良いことです。
ブラッド

1
私は500Gのibdata1ファイルを持っていますが、そこに格納されていたほとんどすべてのデータがデータベースごとのファイルに格納されています。この膨大なスペースの無駄を縮小する必要があります。
フランクスター2017

2
完全なナンセンス!アップ膨満感続けファイルはトリミングする必要がありますが、スペースが不足しているかどうかではありません。私はそれを呼びますstorage leak
ADTC、2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.