ibdata1肥大化の対処法

`ibdata1` のサイズ削減手順において、InnoDB以外のストレージエンジン（例：MyISAM）を使用しているテーブルが存在する場合、いくつかの追加の考慮事項があります。以下に詳細を説明します。

## **1. InnoDB以外のストレージエンジンが存在する場合の影響**

### **a. `ibdata1` と非InnoDBテーブル**

- **InnoDBテーブル**: `ibdata1` は主にInnoDBのシステムテーブルスペースとして機能し、InnoDBテーブルのデータやインデックス、Undoログなどが格納されています。
- **非InnoDBテーブル（例：MyISAM）**: MyISAMなどの他のストレージエンジンを使用しているテーブルは、各テーブルごとに `.MYD`（データファイル）および `.MYI`（インデックスファイル）が存在し、`ibdata1` には格納されません。

**結論**: 基本的には、非InnoDBテーブルは `ibdata1` のサイズ削減手順に直接影響されません。ただし、以下の点に注意が必要です。

### **b. 全テーブルエンジンの確認**

作業を始める前に、データベース内の全テーブルがInnoDBかどうかを確認することをお勧めします。これにより、予期せぬ影響を防ぐことができます。

```sql
SELECT TABLE_SCHEMA, TABLE_NAME, ENGINE 
FROM information_schema.TABLES 
WHERE TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys');
```

このクエリにより、各テーブルのストレージエンジンを一覧表示できます。

## **2. 手順の調整と追加の注意点**

InnoDB以外のテーブルが存在する場合でも、基本的な手順は以下の通りですが、いくつかの追加のステップと確認が必要です。

### **ステップ1: データベースのバックアップ**

#### **a. 全テーブルエンジンを含むバックアップの取得**

`mysqldump` コマンドを使用して全データベースをダンプする際、InnoDBと非InnoDBの両方のテーブルを含めることができます。既に `--all-databases` オプションを使用しているため、全てのテーブルがバックアップされます。

```bash
mysqldump -u root -p --all-databases --routines --triggers --single-transaction > /path/to/backup/all_databases.sql
```

**注意事項:**
- **`--single-transaction`**: InnoDBテーブルに対して一貫性のあるバックアップを取得しますが、MyISAMテーブルはトランザクションをサポートしていないため、データの整合性を保つために、ダンプ前に書き込みを停止するか、適切な手順を踏むことを検討してください。
- **ロックの検討**: 必要に応じて、バックアップ中にテーブルロックをかけるなどの対策を講じてください。

#### **b. バックアップの検証**

ダンプファイルが正しく作成されたことを確認します。

```bash
head /path/to/backup/all_databases.sql
```

また、テスト環境でリストアを行い、バックアップが正しく機能することを確認することを強くお勧めします。

### **ステップ2: MySQL の停止**

```bash
sudo systemctl stop mysql
```

**確認:**
MySQLが正常に停止したことを確認します。

```bash
sudo systemctl status mysql
```

### **ステップ3: `innodb_file_per_table` の有効化**

既に説明した通り、`innodb_file_per_table` を有効にすることで、InnoDBテーブルが個別の `.ibd` ファイルに格納され、`ibdata1` の肥大化を防げます。

#### **a. MySQL 設定ファイルの編集**

```bash
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
```

#### **b. `[mysqld]` セクションに以下を追加**

```ini
[mysqld]
innodb_file_per_table=1
```

**確認:**
他の設定との競合がないか、設定ファイル全体を確認してください。

#### **c. 設定ファイルを保存して閉じる**

### **ステップ4: `ibdata1` とログファイルの削除**

**⚠️ 注意:** 以下の操作はデータを失うリスクがあるため、必ずバックアップを取得してから実施してください。

```bash
sudo rm /var/lib/mysql/ibdata1
sudo rm /var/lib/mysql/ib_logfile0
sudo rm /var/lib/mysql/ib_logfile1
```

**注:**
- **非InnoDBテーブルのファイルに注意**: MyISAMテーブルなどの非InnoDBテーブルは、`ibdata1` とは別のファイル（`.MYD`、`.MYI`）にデータが保存されているため、これらのファイルを削除しないよう注意してください。
- **データディレクトリの確認**: MySQLのデータディレクトリが異なる場合は、適宜パスを変更してください。

### **ステップ5: MySQL の再起動**

```bash
sudo systemctl start mysql
```

**確認:**
MySQLが正常に起動し、新しい `ibdata1` とログファイルが作成されたことを確認します。

```bash
sudo systemctl status mysql
ls -lh /var/lib/mysql/ibdata1 /var/lib/mysql/ib_logfile0 /var/lib/mysql/ib_logfile1
```

### **ステップ6: データベースのリストア**

バックアップからデータベースをリストアします。

```bash
mysql -u root -p < /path/to/backup/all_databases.sql
```

**注意事項:**
- **リストア時のエラー確認**: リストア中にエラーが発生した場合、ログを確認して適切に対処してください。

### **ステップ7: データベースの確認**

MySQLにログインし、データが正しく復元されているか確認します。

```bash
mysql -u root -p
SHOW DATABASES;
```

個別のテーブルやデータの整合性も確認してください。

### **ステップ8: 各テーブルの最適化**

`innodb_file_per_table` を有効にした後、各InnoDBテーブルを最適化して不要なスペースを解放します。

```sql
OPTIMIZE TABLE your_database.your_table;
```

**非InnoDBテーブルの最適化:**

MyISAMテーブルなどの場合も、必要に応じて最適化を行います。

```sql
OPTIMIZE TABLE your_database.your_table ENGINE=MyISAM;
```

**全テーブルの一括最適化:**

スクリプトを使用して、全テーブルを自動的に最適化することも可能です。以下はBashスクリプトの一例です。

```bash
#!/bin/bash

DB_USER="root"
DB_PASS="your_password"

mysql -u $DB_USER -p$DB_PASS -e 'SHOW TABLES' your_database | while read table; do
    if [ "$table" != "Tables_in_your_database" ]; then
        ENGINE=$(mysql -u $DB_USER -p$DB_PASS -e "SHOW TABLE STATUS LIKE '$table'" your_database | awk 'NR==2 {print $2}')
        if [ "$ENGINE" == "InnoDB" ]; then
            mysql -u $DB_USER -p$DB_PASS -e "OPTIMIZE TABLE $table" your_database
        elif [ "$ENGINE" == "MyISAM" ]; then
            mysql -u $DB_USER -p$DB_PASS -e "OPTIMIZE TABLE $table ENGINE=MyISAM" your_database
        fi
    fi
done
```

**注意事項:**
- スクリプトを実行する前に、`DB_USER` と `DB_PASS` を適切に設定してください。
- スクリプトは全テーブルを対象とするため、実行前にバックアップが確実に取られていることを確認してください。

## **3. 追加の考慮事項**

### **a. テーブルエンジンの確認と変更**

もし一部のテーブルが非InnoDB（例：MyISAM）を使用しており、InnoDBへの移行が可能であれば、ストレージエンジンをInnoDBに変更することで、全体の管理が容易になります。

```sql
ALTER TABLE your_database.your_table ENGINE=InnoDB;
```

**注意事項:**
- **互換性の確認**: テーブルエンジンを変更する前に、アプリケーションとの互換性や特定の機能が保持されることを確認してください。
- **パフォーマンスの評価**: InnoDBは多くの場合優れたパフォーマンスを提供しますが、特定のユースケースでは異なる結果となる可能性があります。

### **b. 定期的なメンテナンス**

- **バックアップの自動化**: 定期的なバックアップを自動化し、バックアップの健全性を定期的に確認します。
- **モニタリングの強化**: `ibdata1` のサイズだけでなく、全体のデータベースの健全性やパフォーマンスをモニタリングするツール（例：Percona Monitoring and Management、Nagios、Zabbix）を導入します。

### **c. ストレージの拡張**

データベースのサイズが急速に増加している場合、ストレージの拡張やデータのアーカイブを検討します。不要なデータの削除やアーカイブにより、ディスクスペースの効率的な使用が可能となります。

## **4. リスクと注意点の再確認**

- **データ損失のリスク**: バックアップが不完全な場合、データの損失が発生する可能性があります。バックアップが正常に機能することを複数回確認してください。
- **ダウンタイムの計画**: この手順ではMySQLサービスを停止するため、ウェブサービスに影響が出ます。トラフィックが少ない時間帯に作業を計画してください。
- **設定ファイルの誤り**: `my.cnf` ファイルの設定ミスはMySQLの起動失敗につながります。設定変更後は、設定ファイルのシンタックスチェックを行うことを推奨します。

```bash
sudo mysqld --verbose --help | grep -A 1 'Default options' 
```

または、設定ファイルを再確認してください。

- **ストレージエンジンの一貫性**: 全テーブルが適切なストレージエンジンを使用していることを確認し、必要に応じて調整します。

## **まとめ**

InnoDB以外のストレージエンジンを使用しているテーブルが存在する場合でも、`ibdata1` のサイズ削減手順自体は基本的に問題ありません。ただし、以下の点に留意することで、より安全かつ効果的に作業を進めることができます。

1. **全テーブルのストレージエンジンを確認**し、必要に応じてInnoDBへの移行を検討する。
2. **バックアップが完全であることを確認**し、テスト環境でのリストアも実施する。
3. **非InnoDBテーブルに対する影響を理解**し、削除や操作を行わないよう注意する。
4. **定期的なメンテナンスとモニタリング**を実施し、将来的な問題を未然に防ぐ。