web-dev-qa-db-ja.com

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

Mysql innodbストレージエンジンを削除して、削除されたテーブルのデータを保存しないようにすることは可能ですか?

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

128
Bryan Field

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

/var/lib/mysql/ibdata1はInnoDBインフラストラクチャで最も忙しいファイルであることに注意してください。通常、6種類の情報が格納されます。

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

InnoDBアーキテクチャ

InnoDB Architecture

多くの人々は、ディスクスペースの管理とパフォーマンスの向上を期待して複数のibdataファイルを作成しますが、その考えは間違っています。

OPTIMIZE TABLE を実行できますか?

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

  • ibdata1内でテーブルのデータとインデックスを連続させます
  • 連続したデータページとインデックスページがに追加されるため、ibdata1が大きくなりますibdata1に追加されます

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

OPTIMIZE TABLEinnodb_file_per_table で実行できますか?

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

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

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

.ibdには、そのテーブルのデータページとインデックスページが含まれます。すばらしいです。

悪いニュースibdataに住んでいるmydb.mytableのデータページとインデックスページを抽出するだけです。 mydb.mytableを含むすべてのテーブルのデータディクショナリエントリは、データディクショナリに残ります( ibdata1の画像表現 を参照)。ibdata1 ATこのポイントを簡単に削除することはできません!!!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(またはWindowsではmy.ini)に追加します

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

    (補足:innodb_buffer_pool_sizeの設定にかかわらず、innodb_log_file_sizeinnodb_buffer_pool_sizeの25%であることを確認してください。

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

  6. ibdata*およびib_logfile*を削除します。オプションで、/var/lib/mysqlを除く、/var/lib/mysql/mysql内のすべてのフォルダーを削除できます。

  7. MySQLを起動します(これにより、ibdata1 [デフォルトで10MB]と、それぞれ1Gでib_logfile0およびib_logfile1が再作成されます)。

  8. SQLData.sqlをインポート

現在、ibdata1は成長しますが、各InnoDBテーブルはibdata1の外側に存在するため、テーブルメタデータのみが含まれます。 ibdata1には、InnoDBデータと他のテーブルのインデックスが含まれなくなります。

たとえば、mydb.mytableという名前のInnoDBテーブルがあるとします。 /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としての私のキャリアの中でこれを何度も行ってきました。実際、これを初めて行ったとき、50GBibdata1ファイルをわずか500MBに縮小しました!

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

警告

ステップ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

手順5で innodb_log_file_sizeinnodb_buffer_pool_size の25%に設定することに関しては、これはかなり古いルールです。

July 03, 2006に戻って、Perconaには素敵な記事 なぜ適切なinnodb_log_file_sizeを選ぶべきか がありました。その後、Nov 21, 2008で、Perconaは (1時間分の変更を保持するピークワークロードに基づいて適切なサイズを計算する方法 に関する別の記事をフォローしました。

それ以来、ログサイズの計算と、これら2つのPerconaの記事を参照した場所について、DBA StackExchangeに投稿しました。

個人的には、私はまだ初期設定のために25%のルールを使用します。その後、実稼働環境でワークロードをより正確に判断できるため、メンテナンスサイクル中にわずか数分で ログのサイズを変更できます .

341
RolandoMySQLDBA

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

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

4
bigjeff