web-dev-qa-db-ja.com

mysqlでibdataのサイズを削減する最良の方法は何ですか?

ibdataファイルのサイズが日々増加する運用サーバーがいくつかあります。

すでに290GBのスペースを消費しています。

サーバーのテーブルはほとんどInnoDBであり、読み取りと書き込みの要求が高くなります。

ログファイルのサイズも増加します。テーブルには膨大な量のデータがあります。

両方の増加するサイズを制御するにはどうすればよいですか?

innodb_file_per_tableを使用していません。

66
Abdul Manaf

InnoDBインフラストラクチャで最もビジーなファイルは/ var/lib/mysql/ibdata1であることに注意してください

通常、このファイルには多くのクラスの情報が格納されます( innodb_file_per_table が0の場合)

  • テーブルデータ
  • テーブルインデックス
  • MVCC(マルチバージョン同時実行制御)データ
    • ロールバックセグメント
    • テーブルスペースを元に戻す
  • テーブルのメタデータ
  • 図式表現 を参照してください

多くの人が複数のibdataファイルを作成して、ディスクスペースの管理とパフォーマンスの向上を期待しています。それは役に立ちません。

残念ながら、ibdata1に格納されているInnoDBテーブルに対するOPTIMIZE TABLEは2つのことを行います。

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

innodb_file_per_table を使用して、ibdata1からテーブルデータとテーブルインデックスを分離し、それらを個別に管理できます。 ibdata1を一度に縮小するには、次のことを行う必要があります

ステップ01)MySQLDumpすべてのデータベースをSQLテキストファイル(SQLData.sqlと呼びます)( 詳細はこちら

ステップ02)すべてのデータベースをドロップします(mysqlperformance_schema、およびinformation_schemaを除く)

ステップ03)mysqlをシャットダウンします

ステップ04)/etc/my.cnfに次の行を追加します

[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_sizeがinnodb_buffer_pool_sizeの25%であることを確認してください。

ステップ05)ibdata1、ib_logfile0およびib_logfile1を削除します

この時点では、/ var/lib/mysqlにmysqlスキーマのみがあるはずです。

ステップ06)mysqlを再起動します

これにより、ibdata1が10MB、ib_logfile0とib_logfile1がそれぞれ1Gで再作成されます。

ステップ07)SQLData.sqlをmysqlに再ロードします

ibdata1は大きくなりますが、テーブルメタデータのみが含まれます

各InnoDBテーブルはibdata1の外に存在します

Mydb.mytableという名前のInnoDBテーブルがあるとします。/var/lib/mysql/mydbに移動すると、テーブルを表す2つのファイルが表示されます。

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

ibdata1にInnoDBデータとインデックスが含まれることはなくなります。

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

私はこれをMySQL DBAとしてのキャリアの中で何度も行ってきました

実際、これを初めて行ったとき、50GBのibdata1ファイルを500MBに縮小しました。

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

MyISAMとInnoDBに保存されている実際のデータの量を確認するには、次のクエリを実行してください。

SELECT IFNULL(B.engine,'Total') "Storage Engine",
CONCAT(LPAD(REPLACE(FORMAT(B.DSize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Data Size", CONCAT(LPAD(REPLACE(
FORMAT(B.ISize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Index Size", CONCAT(LPAD(REPLACE(
FORMAT(B.TSize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Table Size"
FROM (SELECT engine,SUM(data_length) DSize,SUM(index_length) ISize,
SUM(data_length+index_length) TSize FROM information_schema.tables
WHERE table_schema NOT IN ('mysql','information_schema','performance_schema')
AND engine IS NOT NULL GROUP BY engine WITH ROLLUP) B,
(SELECT 3 pw) A ORDER BY TSize;
110
RolandoMySQLDBA