方法:mysql InnoDBストレージエンジンをクリーンアップしますか?


133

mysqlのinnodbストレージエンジンをクリーンアップして、削除されたテーブルのデータを格納しないようにすることは可能ですか?

または毎回新しいデータベースを再構築する必要がありますか?


MySQLが削除されたテーブルからのデータを保存していると思うのはなぜですか?
Robert Munteanu

1
私は巨大なテーブルの全体の束をドロップすると、私のInnoDBストレージファイルは収縮しない
ブライアン・フィールド

2
@RobertMunteanu:bugs.mysql.com/bug.php?id
最大

回答:


351

InnoDBに関するより完全な回答を次に示します。これは少し長いプロセスですが、努力する価値があります。

これ/var/lib/mysql/ibdata1はInnoDBインフラストラクチャで最もビジーなファイルであることを覚えておいてください。通常、6つのタイプの情報を格納します。

  • テーブルデータ
  • テーブルインデックス
  • MVCC(マルチバージョン同時実行制御)データ
    • ロールバックセグメント
    • スペースを元に戻す
  • テーブルメタデータ(データディクショナリ)
  • 二重書き込みバッファー(OSキャッシュへの依存を防ぐためのバックグラウンド書き込み)
  • バッファーの挿入(一意でないセカンダリインデックスへの変更の管理)
  • を参照してください Pictorial Representation of ibdata1

InnoDBアーキテクチャ

InnoDBアーキテクチャ

多くの人が複数のibdataファイルを作成して、ディスク領域の管理とパフォーマンスを向上させることを期待していますが、その考えは誤っています。

走ってもOPTIMIZE TABLEいいですか?

残念ながら、OPTIMIZE TABLE共有テーブルスペースファイルに格納されているInnoDBテーブルに対して実行すると、次のibdata12つのことが行われます。

  • テーブルのデータとインデックスを内部で隣接させる ibdata1
  • 作るには、ibdata1連続したデータとインデックスページがされているため、成長追加しますibdata1

ただし、テーブルデータとテーブルインデックスを分離ibdata1して、個別に管理することができます。

私は実行することはできOPTIMIZE TABLEinnodb_file_per_table

に追加innodb_file_per_tableするとします/etc/my.cnf (my.ini)。次にOPTIMIZE TABLE、すべてのInnoDBテーブルで実行できますか?

良いニュース:有効にして実行するOPTIMIZE TABLEと、そのテーブルのファイルinnodb_file_per_tableが生成.ibdされます。たとえば、mydb.mytabledatadir がのテーブルがある場合/var/lib/mysql、次のようになります。

  • /var/lib/mysql/mydb/mytable.frm
  • /var/lib/mysql/mydb/mytable.ibd

.ibdそのテーブルのデータ・ページとインデックスページが含まれます。すごい。

悪い知らせ:あなたがしているのはmydb.mytable、に住んでいるのデータページとインデックスページを抽出することだけですibdata。を含むすべてのテーブルのデータディクショナリエントリはmydb.mytable、まだデータディクショナリに残っています(ibdata1の図解を参照)。この時点で単純に削除することはできませんibdata1!!! ibdata1全く縮んでおりませんのでご了承ください。

InnoDBインフラストラクチャのクリーンアップ

ibdata1一度にすべてを縮小するには、次のことを行う必要があります。

  1. mysqldumpすべてのデータベースを.sqlテキストファイルにダンプする(例:をSQLData.sql使用)(以下で使用)

  2. すべてのデータベース(mysqlおよびを除くinformation_schema)を削除します。警告:予防策として、次のスクリプトを実行して、すべてのユーザー権限が確実に設定されていることを確認してください。

    mkdir /var/lib/mysql_grants
    cp /var/lib/mysql/mysql/* /var/lib/mysql_grants/.
    chown -R mysql:mysql /var/lib/mysql_grants
  3. mysqlにログインして実行しますSET GLOBAL innodb_fast_shutdown = 0;(これにより、ib_logfile0およびからのすべての残りのトランザクションの変更が完全にフラッシュされますib_logfile1)。

  4. MySQLをシャットダウンする

  5. 次の行を/etc/my.cnf(またはmy.iniWindowsに)追加します

    [mysqld]
    innodb_file_per_table
    innodb_flush_method=O_DIRECT
    innodb_log_file_size=1G
    innodb_buffer_pool_size=4G

    (補足:の設定が何であれ、の25%であるinnodb_buffer_pool_sizeことを確認してください。innodb_log_file_sizeinnodb_buffer_pool_size

    またinnodb_flush_method=O_DIRECT、Windowsでは使用できません)

  6. 削除ibdata*およびib_logfile*必要に応じて、あなたは内のすべてのフォルダを削除することができ、/var/lib/mysql除き、/var/lib/mysql/mysql

  7. MySQLを起動します(これibdata1により[デフォルトで10MB] が再作成され、ib_logfile0さらにib_logfile11Gで作成されます)。

  8. インポート SQLData.sql

これで、ibdata1は引き続き増加しますが、各InnoDBテーブルがの外部に存在するため、テーブルメタデータのみが含まれますibdata1ibdata1InnoDBデータと他のテーブルのインデックスは含まれなくなります。

たとえば、というInnoDBテーブルがあるとしますmydb.mytable。を見ると/var/lib/mysql/mydb、表を表す2つのファイルが表示されます。

  • mytable.frm (ストレージエンジンヘッダー)
  • mytable.ibd (テーブルデータとインデックス)

innodb_file_per_tableオプション/etc/my.cnfを使用するOPTIMIZE TABLE mydb.mytableと、実行でき、ファイル/var/lib/mysql/mydb/mytable.ibdは実際に縮小されます。

私はこれをMySQL DBAとしてのキャリアの中で何度も行ってきました。実際、これを初めて実行したときに、50 GBの ibdata1ファイルを500 MBに縮小しました。

試してみる。これについてさらに質問がある場合は、質問してください。私を信じて; これは短期的にも長期的にも機能します。

警告

手順6で、mysqlスキーマの削除が開始されたためにmysqlを再起動できない場合は、手順2に戻りmysqlます。スキーマの物理コピーを作成しました。次のようにして復元できます。

mkdir /var/lib/mysql/mysql
cp /var/lib/mysql_grants/* /var/lib/mysql/mysql
chown -R mysql:mysql /var/lib/mysql/mysql

手順6に戻って続行します

更新2013-06-04 11:13 EDT

設定に関してはinnodb_log_file_sizeを 25%にinnodb_buffer_pool_sizeの毛布ルールはかなり古い学校であることを、ステップ5で。

戻ってJuly 03, 2006、Perconaは、適切なinnodb_log_file_sizeを選択する理由についての素晴らしい記事がありました。その後、Nov 21, 2008Perconaは、1時間分の変更を維持しながら、ピーク時のワークロードに基づいて適切なサイズを計算する方法に関する別の記事を続けました

それ以来、DBA StackExchangeに、ログサイズの計算と、これら2つのPerconaの記事をどこで参照したかについての記事を書きました。

個人的には、初期設定では25%ルールのままにします。次に、本番環境ではワークロードをより正確に判断できるため、メンテナンスサイクル中に数分でログのサイズを変更できます


9
また、innodb_file_per_tableオプションを使用して、1つのサーバーに200のテーブルを持つ200のデータベースを使用し、異なるデータベースを異なるパーティションにシンボリックリンクすることができました。
Dave Rix、2011年

2
@SeanDowneyところでinnodb_open_tables、必要に応じてレイズすることを忘れないでください。デフォルトは300です
RolandoMySQLDBA

2
@ giorgio79では、一括挿入をより大きな値に設定する必要があります。これは良い点です。私の答えにあなたの質問の本質を加えます。
RolandoMySQLDBA、2012年

3
32ビットシステムでは、innodb_buffer_pool_sizeの 4Gb値は許可されません。Mysqlはinnodbを無効にした状態で静かに起動し、復元されたテーブルはmyisamに変更されます。少し小さい値を使用して修正します。
David

5
いい神。私はこれがおそらく私がSOくそー良い仕事で今まで見た中で最高の答えの1つだと言いたいのです、先生。154gのdbをインポートするときにエラー2013(HY000)が発生したときの問題の解決策を見つけるのに役立ちました。すばらしい答えをありがとう!
ジョシュブラウン

4

InnoDBエンジンは削除されたデータを保存しません。行を挿入および削除すると、未使用のスペースがInnoDBストレージファイル内に割り当てられたままになります。時間の経過とともに全体的なスペースは減少しませんが、「削除および解放された」スペースはDBサーバーによって自動的に再利用されます。

テーブルを手動で再編成することにより、エンジンが使用するスペースをさらに調整および管理できます。これを行うには、mysqldumpを使用して影響を受けるテーブルのデータをダンプし、テーブルをドロップし、mysqlサービスを再起動してから、ダンプファイルからテーブルを再作成します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.