[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7. MySQL のテーブル型

MySQL バージョン 3.23.6 より、3 種類の基本テーブル形式(ISAMHEAPMyISAM)を選択できるようになりました。これより新しい MySQL のバージョンでは、コンパイルの方法に応じて追加のテーブル型(InnoDB または BDB)をサポートしています。1 つのデータベースに異なる型のテーブルを収容することができます。

新しいテーブルを作成するときに、そのテーブルの型を MySQL に通知できます。通常、デフォルトのテーブル型は MyISAM です。

MySQL では、テーブル定義とカラム定義を保持する `.frm' ファイルが必ず作成されます。テーブルのインデックスとデータは、テーブル型に応じて、このファイル以外の 1 つ以上のファイルに格納されます。

コンパイルまたはアクティブ化されていないテーブル型を使用しようとすると、MySQL によってそのテーブル型の代わりに MyISAM 型のテーブルが作成されます。この動作は、さまざまなテーブル型をサポートする MySQL サーバ間でテーブルをコピーする場合に便利です(ほとんどの場合、マスタサーバは安全性を高めるためにトランザクションストレージエンジンをサポートし、スレーブサーバは処理速度を高めるために非トランザクションストレージエンジンのみをサポートしています)。

MySQL の初心者は、このテーブル型の自動変更に戸惑うかもしれません。この点については、バージョン 4.1 で新しいクライアント/サーバプロトコルに警告を導入し、テーブル型が自動変更される際に警告を生成する方法で対応する予定です。

ALTER TABLE ステートメントを使用すれば、テーブルを別の型に変換できます。 「6.5.4 ALTER TABLE 構文」 節 参照 。

MySQL では 2 種類のテーブルをサポートしていることに注意してください。1 つはトランザクションセーフのテーブル(InnoDBBDB)、もう 1 つは非トランザクションセーフのテーブル(HEAPISAMMERGEMyISAM)です。

トランザクションセーフのテーブル(TST)には次の利点があります。

InnoDB テーブルを使用するには、少なくとも innodb_data_file_path 起動オプションを使用する必要があることに注意してください。 「7.5.3 InnoDB 起動オプション」 節 参照 。

非トランザクションセーフのテーブル(NTST)には次の利点があります。

同じステートメントで TST テーブルと NTST テーブルを組み合わせると、両方の利点を活かすことができます。

7.1 MyISAM テーブル   
7.2 MERGE テーブル   
7.3 ISAM テーブル   
7.4 HEAP テーブル   
7.5 InnoDB テーブル   
7.6 BDB または BerkeleyDB テーブル   


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.1 MyISAM テーブル

MyISAM は、MySQL バージョン 3.23 でのデフォルトのテーブル型です。この型は ISAM コードに基づいており、多数の便利な拡張機能を備えています。

インデックスは `.MYI'(MYIndex)拡張子の付いたファイルに、データは `.MYD'(MYData)拡張子の付いたファイルにそれぞれ格納されます。MyISAM テーブルは、myisamchk ユーティリティで検査および修復することができます。 「4.5.6.7 myisamchk を使用したクラッシュのリカバリ」 節 参照 。 また、MyISAM テーブルを myisampack で圧縮することで、使用する領域を大幅に削減できます。 「4.8.4 myisampack(MySQL 圧縮読み取り専用テーブルジェネレータ)」 節 参照 。

MyISAM の新機能は次のとおりです。

MyISAM は、MySQL で近い将来使用可能となる次の機能もサポートしています。

通常、インデックスファイルは ISAM よりも MyISAM の方がはるかに小さいので注意してください。つまり、MyISAM は一般に ISAM よりも少ないシステムリソースを使用しますが、圧縮されたインデックスへデータを挿入する際により多くの CPU 時間を必要とします。

次に示す mysqld のオプションを使用して、MyISAM テーブルの動作を変更することができます。 「4.6.8.4 SHOW VARIABLES 節 参照 。

オプション 説明
--myisam-recover=# クラッシュしたテーブルの自動リカバリ。
-O myisam_sort_buffer_size=# テーブルをリカバリする際に使用されるバッファ。
--delay-key-write=ALL すべての MyISAM テーブルに対して、書き込み間でキーバッファをフラッシュしない。
-O myisam_max_extra_sort_file_size=# 速度は遅くても安全なキーキャッシュインデックス作成方法をどの時点で使用するかを MySQL が判断できるようにする。注意: このパラメータを指定する単位として、4.0.3 より前はメガバイト、このバージョンからはバイトを使用する。
-O myisam_max_sort_file_size=# テンポラリファイルがこの値を超えた場合に、作成されたインデックスに対して高速なソートインデックス方法を使用しない。注意: このパラメータを指定する単位として、4.0.3 より前はメガバイト、このバージョンからはバイトを使用する。
-O bulk_insert_buffer_size=# バルク挿入の最適化で使用されるツリーキャッシュのサイズ。注意: これはスレッド当たりの制限値。

--myisam-recover=# を指定して mysqld を起動すると、自動リカバリがアクティブ化されます。 「4.1.1 mysqld コマンドラインオプション」 節 参照 。 テーブルが開く際に検査されます。検査の内容は、テーブルにクラッシュのマークが付いているかどうか、またはテーブルのオープンカウント変数が 0 ではなく、かつ --skip-external-locking で実行しているかどうかです。上記のどちらかが当てはまる場合は、次の処理が行われます。

myisam-recover のオプションとして FORCE を指定しなかった場合に、直前に完了したステートメントからすべてのレコードをリカバリできないときは、自動修復が中止され、エラーファイルに次のエラーメッセージが書き込まれます。

 
Error: Couldn't repair table: test.g00pages

FORCE オプションを指定していた場合は、上記のメッセージの代わりに次の警告がエラーファイルに書き込まれます。

 
Warning: Found 344 of 354 rows when repairing ./test/g00pages

注意: BACKUP オプションを指定して自動リカバリを実行する場合は、`tablename-datetime.BAK' のような名前のファイルをデータベースディレクトリからバックアップメディアに自動的に移動する cron スクリプトを用意する必要があることに注意してください。

「4.1.1 mysqld コマンドラインオプション」 節 参照 。

7.1.1 キーに必要な領域   
7.1.2 MyISAM テーブル形式   
7.1.3 MyISAM テーブルの問題   


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.1.1 キーに必要な領域

MySQL ではさまざまなインデックスをサポートしていますが、一般に使用されるのは ISAM または MyISAM です。これらは B ツリーインデックスを使用します。このインデックスファイルのサイズは、すべてのキーについて (キー長+4)/0.67 を計算し、それを合計することで大まかに算出できます(これは、すべてのキーがソートされた順に挿入され、かつキーが一切圧縮されないという、最悪のケースを想定しています)。

文字列インデックスでは空白が圧縮されます。インデックスの最初の部分が文字列の場合は、プリフィックスも圧縮されます。文字列カラムに含まれる後続の空白が長い場合、またはそのカラムが VARCHAR カラムであるためにその長さがフルに使用されることがない場合は、空白の圧縮によってインデックスファイルが上記の数値よりも小さくなります。プリフィックスの圧縮は、文字列で始まるキーで使用されます。同一のプリフィックスを持つ文字列が多数存在する場合は、プリフィックスの圧縮が役立ちます。

MyISAM テーブルでは、テーブル作成時に PACK_KEYS=1 を指定することで、数値のプリフィックスを圧縮することもできます。この機能は、数値が上位バイトから順に格納される場合に、同一のプリフィックスを持つ整数キーが多数あるときに役立ちます。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.1.2 MyISAM テーブル形式

MyISAM は、3 種類のテーブル型をサポートします。そのうち 2 つは、使用しているカラムの型に応じて自動的に選択されます。3 番目の圧縮テーブルは、myisampack ツールによってのみ作成されます。

BLOB 値を持たないテーブルを CREATE または ALTER する際に、ROW_FORMAT=# テーブルオプションを使用してテーブル形式を強制的に DYNAMIC または FIXED に設定できます。将来的には、ALTER TABLEROW_FORMAT=compressed | default を指定することで、テーブルを圧縮/展開できるようになります。 「6.5.3 CREATE TABLE 構文」 節 参照 。

7.1.2.1 静的(固定長)テーブルの特性   
7.1.2.2 動的テーブルの特性   
7.1.2.3 圧縮テーブルの特性   


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.1.2.1 静的(固定長)テーブルの特性

これはデフォルトの形式です。この形式は、テーブルに VARCHARBLOB、または TEXT 型のカラムが含まれていない場合に使用されます。

この形式は最も単純かつ最も安全です。また、ディスク上の形式としては最も高速です。速度が速いのは、ディスク上で簡単にデータを検出できるためです。検索の対象がインデックスと静的形式を使用している場合、操作はきわめて単純です。単にレコードの番号にレコードの長さを掛けるだけです。

また、テーブルをスキャンする際にも、1 回のディスク読み取りで一定数のレコードを簡単に読み取ることができます。

固定サイズの MyISAM ファイルへ書き込んでいるときにコンピュータがクラッシュした場合の保全性も証明されています。この場合、myisamchk によって各レコードの開始位置と終了位置が簡単に割り出されます。したがって、通常は、部分的に書き込まれたレコードを除くすべてのレコードを回復できます。MySQL ではすべてのインデックスをいつでも再構築できることに注意してください。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.1.2.2 動的テーブルの特性

この形式は、テーブルに VARCHARBLOB、または TEXT カラムが含まれている場合、あるいはテーブルが ROW_FORMAT=dynamic で作成された場合に使用されます。

この形式は少し複雑です。各レコードにそれぞれの長さを記録したヘッダが必要となるからです。1 つのレコードが、更新によって長くなったために、複数の場所に存在することになる可能性もあります。

OPTIMIZE table または myisamchk を使用して、テーブルをデフラグメント化することができます。VARCHAR または BLOB カラムと同じテーブル内に、頻繁にアクセス/変更する静的データがある場合は、フラグメント化を回避するために動的なカラムを他のテーブルに移動するとよいでしょう。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.1.2.3 圧縮テーブルの特性

これは、オプションの myisampack ツール(ISAM テーブルでは pack_isam)で生成される読み取り専用テーブルです。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.1.3 MyISAM テーブルの問題

MySQL がデータの格納に使用するファイル形式は広範な検査を受けていますが、データベーステーブルの破損を招きかねない状況は常に存在します。

7.1.3.1 MyISAM テーブルが破損した場合   
7.1.3.2 クライアントがテーブルを使用している、またはテーブルを適切に閉じていない   


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.1.3.1 MyISAM テーブルが破損した場合

MyISAM は信頼性の高いテーブル形式ですが(テーブルに対するすべての変更は SQL ステートメントから制御が戻る前に書き込まれます)、それでも以下の状況が発生した場合はテーブルが破損するおそれがあります。

テーブルが破損すると、一般に次のような現象が見られます。

テーブルが破損していないかどうかは、CHECK TABLE コマンドで確認できます。 「4.5.4 CHECK TABLE 構文」 節 参照 。

破損したテーブルは、REPAIR TABLE で修復できます。 「4.5.5 REPAIR TABLE 構文」 節 参照 。 また、mysqld が稼働していないときに、myisamchk コマンドを使ってテーブルを修復することもできます。 myisamchk syntax

テーブルが大きく破損している場合は、原因を突き止める必要があります。 「A.4.1 MySQL が何度もクラッシュする場合に行うこと」 節 参照 。

この場合に最も重要なのは、mysqld が強制終了されたときにテーブルが破損したのかを確認することです(これは、mysqld エラーファイルに restarted mysqld という行が最近記録されたかどうかをチェックすることで簡単に検証できます)。これが該当しない場合は、その破損のテストケースを作成してみる必要があります。 「E.1.6 テーブルが破損した場合にテストケースを作成する」 節 参照 。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.1.3.2 クライアントがテーブルを使用している、またはテーブルを適切に閉じていない

MyISAM `.MYI' ファイルのヘッダには、テーブルが適切に閉じられているかをチェックするためのカウンタがあります。

CHECK TABLE または myisamchk から次の警告が返されることがあります。

 
# clients is using or hasn't closed the table properly

これは、このカウンタがずれていることを意味します。テーブルの破損を意味しているわけではありませんが、少なくともテーブルを検査して問題がないことを確認する必要があります。

カウンタの仕組みは次のとおりです。

つまり、カウンタがずれる可能性があるのは、次の場合に限られます。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.2 MERGE テーブル

MERGE テーブルは、MySQL バージョン 3.23.25 で新たに導入されました。コードはまだガンマ版ですが、比較的安定しているはずです。

MERGE テーブル(MRG_MyISAM テーブルとも呼ばれます)は、1 つのテーブルとして使用できる同一の MyISAM テーブルの集合です。テーブルの集合には、SELECTDELETEUPDATE のみを実行できます。MERGE テーブルに対して DROP を実行すると、MERGE の仕様のみが破棄されます。

WHERE なしで DELETE FROM merge_table を使用すると、テーブルに対するマッピングのみが消去され、マップされたテーブルの内容は削除されないことに注意してください(これは 4.1 で修正する予定です)。

同一のテーブルとは、すべてのテーブルが同一のカラムおよびキー情報で作成されていることを意味します。カラムのパック方法が異なるテーブル、保持するカラムがまったく同じでないテーブル、あるいはキーの順序が異なるテーブルはマージできません。ただし、一部のテーブルは myisampack で圧縮できます。 「4.8.4 myisampack(MySQL 圧縮読み取り専用テーブルジェネレータ)」 節 参照 。

MERGE テーブルを作成すると、`.frm' テーブル定義ファイルおよび `.MRG' テーブルリストファイルが作成されます。`.MRG' には、1 つのインデックスファイルとして使用される複数のインデックスファイル(`.MYI' ファイル)のリストのみが含まれています。4.1.1 より前のバージョンでは、使用されるすべてのテーブルを MERGE テーブルと同じデータベースに配置する必要がありました。

今のところ、MERGE テーブルにマップするテーブルに対しては、SELECTUPDATEDELETE の各特権が必要です。

MERGE テーブルには、次のような効果があります。

MERGE テーブルの欠点は次のとおりです。

MERGE テーブルを作成するときに、1 つにまとめたいテーブルを UNION=(list-of-tables) で指定する必要があります。オプションとして、MERGE テーブルへの挿入が UNION リスト内の最初のテーブルと最後のテーブルのどちらで行われるかを、INSERT_METHOD で指定できます。INSERT_METHOD を指定しなかった場合、または NO を指定した場合は、MERGE テーブルに対するすべての INSERT コマンドでエラーが返されます。

次の例は、MERGE テーブルの使い方を示しています。

 
CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, message CHAR(20));
CREATE TABLE t2 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, message CHAR(20));
INSERT INTO t1 (message) VALUES ("Testing"),("table"),("t1");
INSERT INTO t2 (message) VALUES ("Testing"),("table"),("t2");
CREATE TABLE total (a INT NOT NULL AUTO_INCREMENT, message CHAR(20), KEY(a))
             TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;
SELECT * FROM total;

total テーブルではキーが一意にならないため、このテーブルでは UNIQUE または PRIMARY KEY を作成していないことに注意してください。

MySQL サーバの外部から直接 `.MRG' ファイルを操作することもできます。

 
shell> cd /mysql-data-directory/current-database
shell> ls -1 t1.MYI t2.MYI > total.MRG
shell> mysqladmin flush-tables

これで次のような操作を実行できるようになります。

 
mysql> SELECT * FROM total;
+---+---------+
| a | message |
+---+---------+
| 1 | Testing |
| 2 | table   |
| 3 | t1      |
| 1 | Testing |
| 2 | table   |
| 3 | t2      |
+---+---------+

注意: a カラムは、PRIMARY KEY として宣言されていますが、実際には一意ではないことに注意してください。MERGE テーブルでは、これを構成する一連の MyISAM テーブル全体にわたる一意性を確保できないからです。

MERGE テーブルをマップし直すには、次のいずれかの操作を実行します。

7.2.1 MERGE テーブルの問題   


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.2.1 MERGE テーブルの問題

次に挙げるのは、MERGE テーブルに関する既知の問題です。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.3 ISAM テーブル

MySQL バージョン 5.0 では、ISAM テーブル型が廃止されます。MySQL 4.1 では、このテーブル型がソースに含まれていてもコンパイルできません。このテーブルハンドラの実装としては MyISAM の方が優れているため、できるだけ早く ISAM テーブルを MyISAM テーブルに変換する必要があります。

ISAM は、B ツリーインデックスを使用します。インデックスは `.ISM' 拡張子の付いたファイルに保存され、データは `.ISD' 拡張子の付いたファイルに保存されます。ISAM テーブルは、isamchk ユーティリティで検査および修復することができます。 「4.5.6.7 myisamchk を使用したクラッシュのリカバリ」 節 参照 。

ISAM には、次の機能と特性があります。

MyISAM テーブルに当てはまることは、ほとんどの場合 ISAM テーブルにも当てはまります。 「7.1 MyISAM テーブル」 節 参照 。MyISAM テーブルとの主な相違点は次のとおりです。

ISAM テーブルを MyISAM テーブルに変換して mysqlcheck などのユーティリティを使用できるようにするには、ALTER TABLE ステートメントを使用します。

 
mysql> ALTER TABLE tbl_name TYPE = MYISAM;

組み込み式の MySQL では、ISAM テーブルがサポートされません。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.4 HEAP テーブル

HEAP テーブルは、ハッシュインデックスを使用し、メモリに格納されます。これによって処理は速くなりますが、MySQL がクラッシュすると、このテーブルに格納されたすべてのデータが失われます。HEAP は、テンポラリテーブルとして非常に便利です。

MySQL の内部 HEAP テーブルは、オーバフローエリアなしの 100% 動的ハッシュを使用します。フリーリスト用の余分な領域は必要ありません。また、HEAP テーブルでは、ハッシュテーブルで一般に見られる削除 + 挿入に伴う問題も起こりません。

 
mysql> CREATE TABLE test TYPE=HEAP SELECT ip,SUM(downloads) AS down
    ->                   FROM log_table GROUP BY ip;
mysql> SELECT COUNT(ip),AVG(down) FROM test;
mysql> DROP TABLE test;

次に、HEAP テーブルを使用する際の考慮事項を示します。

HEAP テーブルで 1 つのレコードに必要なメモリは、次のように計算します。

 
SUM_OVER_ALL_KEYS(キーの最大長 + sizeof(char*) * 2)
+ ALIGN(レコードの長さ+1, sizeof(char*))

sizeof(char*) は、32 ビットマシンでは 4、64 ビットマシンでは 8 です。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.5 InnoDB テーブル

7.5.1 InnoDB テーブルの概要   
7.5.2 MySQL バージョン 3.23 での InnoDB   
7.5.3 InnoDB 起動オプション   
7.5.4 InnoDB テーブルスペースの作成   
7.5.5 InnoDB テーブルの作成   
7.5.6 InnoDB データファイルとログファイルの追加と削除   
7.5.7 InnoDB データベースのバックアップとリカバリ   
7.5.8 InnoDB データベースを別のマシンに移動する   
7.5.9 InnoDB トランザクションモデルとロック   
7.5.10 パフォーマンスチューニングのヒント   
7.5.11 マルチバージョニングの実装   
7.5.12 テーブルとインデックスの構造   
7.5.13 ファイル領域の管理とディスク I/O   
7.5.14 エラー処理   
7.5.15 InnoDB テーブルの制限事項   
7.5.16 InnoDB の変更履歴   
7.5.17 InnoDB についての問い合わせ先   


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.5.1 InnoDB テーブルの概要

InnoDB は、MySQL における、コミット、ロールバック、クラッシュリカバリの各機能を備えたトランザクションセーフ(ACID 準拠)のストレージエンジンです。InnoDB は、行レベルでロックを行い、SELECT ステートメントで Oracle 式の非ロックの読み取り一貫性(consistent read)を実現します。これらの機能によって、マルチユーザでの並行性とパフォーマンスが向上します。InnoDB ではロックエスカレーションが不要です。InnoDB での行レベルロックはわずかなスペースしか使用しないからです。InnoDB は、MySQL で FOREIGN KEY 制約を最初にサポートしたストレージエンジンです。

InnoDB は、大容量のデータを処理する際に最大限のパフォーマンスを実現するように設計されています。その CPU 効率は、おそらく他のディスクベースのリレーショナルデータベースエンジンのどれよりも優れています。

InnoDB は、高いパフォーマンスを必要とする多くの大規模データベースサイトで実際に使用されています。有名なインターネットニュースサイトの Slashdot.org は、InnoDB 上で稼働しています。Mytrix, Inc. では、1 TB を超えるデータを InnoDB に格納し、別のサイトでは InnoDB で 1 秒間に平均 800 件の挿入/更新を処理しています。

技術的には、InnoDB は MySQL のデータベースバックエンドです。InnoDB は、データとインデックスをキャッシュするための専用のバッファプールをメインメモリに持っています。InnoDB のテーブルとインデックスはテーブルスペースに格納されます。これは、複数のファイル(またはローデバイス)で構成されている場合があります。この点は、各テーブルを個別のファイルに格納する MyISAM テーブルなどとは異なっています。InnoDB テーブルは、ファイルサイズが 2 GB に制限されているオペレーティングシステム上でも、任意のサイズにすることができます。

InnoDB に関する最新情報は、http://www.innodb.com/ で参照できます。InnoDB マニュアルの最新版もこのサイトに収録されています。

InnoDB は、MySQL と同じ GNU GPL License Version 2(1991 年 6 月付け)の下でリリースされています。MySQL/InnoDB を配布する場合に、アプリケーションが GPL ライセンスの制約を満たしていないときは、https://order.mysql.com/?sub=pg&pg_no=1 から MySQL Pro の商用ライセンスを購入する必要があります。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.5.2 MySQL バージョン 3.23 での InnoDB

MySQL バージョン 4.0 より、InnoDB はデフォルトで MySQL に組み込まれています。次の情報は、3.23 シリーズだけに該当します。

InnoDB テーブルは、3.23.34a より MySQL ソースディストリビューションに含まれるようになりました。 ただし 3.23 シリーズでは、InnoDB は MySQL-Max バイナリディストリビューションのみに組み込まれています。Windows の場合は、-Max バイナリが標準のバイナリディストリビューションに含まれています。

InnoDB をサポートする MySQL のバイナリバージョンをダウンロードした場合は、MySQL のマニュアルに従って MySQL のバイナリバージョンをインストールしてください。すでに MySQL-3.23 をインストールしている場合に MySQL-Max を最も簡単にインストールするには、サーバの実行ファイル `mysqld' を、-Max ディストリビューションの実行ファイルで置き換えます。MySQL と MySQL-Max は、サーバの実行ファイルの名前のみが異なります。 「2.2.9 MySQL バイナリディストリビューションのインストール」 節 参照 。 「4.8.5 mysqld-max(拡張 mysqld サーバ)」 節 参照 。

InnoDB をサポートする MySQL をコンパイルするには、MySQL-3.23.34a 以降のバージョンを http://www.mysql.com/ からダウンロードし、--with-innodb オプションで MySQL をコンフィギャします。MySQL ソースディストリビューションのインストールについては、MySQL のマニュアルを参照してください。 「2.3 MySQL ソースディストリビューションのインストール」 節 参照 。

 
cd /path/to/source/of/mysql-3.23.37
./configure --with-innodb

MySQL-Max-3.23 で InnoDB テーブルを使用するには、オプション設定ファイル `my.cnf'(Windows の場合は `my.ini' でも可)の [mysqld] セクションで設定パラメータを指定しなければなりません

3.23 では、少なくとも innodb_data_file_path でデータファイルの名前とサイズを指定する必要があります。`my.cnf' で innodb_data_home_dir を指定しない場合は、デフォルトで MySQL の datadir にこれらのファイルが作成されます。innodb_data_home_dir を空の文字列として指定すれば、innodb_data_file_path でデータファイルへの絶対パスを指定できます。

これを最小限の方法で変更するには、[mysqld] セクションに次の行を追加します。

 
innodb_data_file_path=ibdata:30M

ただし、高いパフォーマンスを得るには、推奨された方法でオプションを指定するのが最善です。 「7.5.3 InnoDB 起動オプション」 節 参照 。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.5.3 InnoDB 起動オプション

MySQL バージョン 3.23 で InnoDB テーブルを有効にする方法については、 「7.5.2 MySQL バージョン 3.23 での InnoDB」 を参照してください。

MySQL-4.0 では、InnoDB テーブルを有効にするために特に何かをする必要はありません。

MySQL-4.0 および MySQL-4.1 のデフォルトの動作として、MySQL の datadir に自動拡張する 10 MB の `ibdata1' ファイルが 1 つと、5 MB の `ib_logfile' ログファイルが 2 つ作成されます(MySQL-4.0.0 および 4.0.1 のデータファイルは 64 MB で、自動拡張しません)。

注意: 高いパフォーマンスを得るには、この後の例に示されている InnoDB の各種パラメータを明示的に設定する必要があります

InnoDB テーブルを使用しない場合は、MySQL オプション設定ファイルに skip-innodb オプションを指定して InnoDB を動作させないようにできます。

 
[mysqld]
skip-innodb

バージョン 3.23.50 および 4.0.2 より、innodb_data_file_path 行の最後のデータファイルを、自動拡張ファイルとして指定できるようになりました。その場合の innodb_data_file_path の構文は次のとおりです。

 
innodb_data_file_path = データファイルのパス:サイズ;データファイルのパス:サイズ;...
...  ;データファイルのパス:サイズ[:autoextend[:max:サイズ]]

最後のデータファイルに autoextend オプションを指定すると、テーブルスペースに空きがなくなった場合に、InnoDB が最後のデータファイルを拡張します。1 回の増分は 8 MB です。次に例を示します。

 
innodb_data_home_dir =
innodb_data_file_path = /ibdata/ibdata1:100M:autoextend
#
# 注意: innodb_data_home_dir に空文字を指定した場合、
# innodb_data_file_path に与えるパスは絶対パスになる

この例では、InnoDB に対し、初期サイズが 100 MB のデータファイルを 1 つだけ作成し、スペースが足りなくなった場合に 8 MB 単位で拡張するように指定しています。ディスクがいっぱいになった場合は、たとえば別のディスクに新たなデータファイルを追加することもできます。その場合は、autoextend が指定されている `ibdata1' のサイズを確認し、そのサイズが 1,024 × 1,024 バイト(= 1 MB)の倍数になるように丸めた値を計算し、計算で得られた値を innodb_data_file_path の `ibdata1' のサイズとして明示的に指定する必要があります。これで、新たなデータファイルを `ibdata1' の後ろに追加できます。

 
innodb_data_home_dir =
innodb_data_file_path = /ibdata/ibdata1:988M;/disk2/ibdata2:50M:autoextend
#
# 注意: この例では最初 100M の ibdata1 が、
# 888M (1024 * 1024の倍数) だけ拡張されていたので、988M の指定になっている。

ファイルシステムの最大ファイルサイズが 2 GB である場合は注意が必要です。InnoDB は、OS の最大ファイルサイズを考慮しません。このようなファイルシステムでは、データファイルの最大サイズを指定する必要があります。

 
innodb_data_home_dir =
innodb_data_file_path = /ibdata/ibdata1:100M:autoextend:max:2000M

単純な `my.cnf' の例。128 MB の RAM と 1 つのハードディスクを搭載したコンピュータを使用しているとします。次に示すのは、InnoDB の `my.cnf' または `my.ini' における設定パラメータの例です。この例では、MySQL-Max-3.23.50 以降、または MySQL-4.0.2 以降が稼働していることを想定しています。この例は、Unix と Windows の両方で、ユーザが InnoDB データファイルとログファイルを複数のディスクに分散させない場合に適しています。この設定パラメータによって、自動拡張するデータファイル `ibdata1' および 2 つの InnoDB ログファイル `ib_logfile0' と `ib_logfile1' が、MySQL の datadir(一般には `/mysql/data')に作成されます。 また、アーカイブされた小さな InnoDB ログファイル `ib_arch_log_0000000000' も datadir に作成されます。

 
[mysqld]
# You can write your other MySQL server options here
# ...
#                                  Datafile(s) must be able to
#                                  hold your data and indexes.
#                                  Make sure you have enough
#                                  free disk space.
innodb_data_file_path = ibdata1:10M:autoextend
#                                  Set buffer pool size to
#                                  50 - 80 % of your computer's
#                                  memory
innodb_buffer_pool_size=70M
innodb_additional_mem_pool_size=10M
#                                  Set the log file size to about
#                                  25 % of the buffer pool size
innodb_log_file_size=20M
innodb_log_buffer_size=8M
#                                  Set ..flush_log_at_trx_commit
#                                  to 0 if you can afford losing
#                                  some last transactions 
innodb_flush_log_at_trx_commit=1

datadirファイルを作成する権限が MySQL サーバにあるかどうかを確認してください

一部のファイルシステムでは、データファイルを 2 GB 未満にする必要があることに注意してください。 ログファイルをすべて合わせたサイズは、4 GB 未満でなければなりません。また、データファイルをすべて合わせたサイズは、10 MB 以上でなければなりません。

InnoDB データベースを初めて作成するときには、コマンドプロンプトから MySQL サーバを起動するのが最善です。 InnoDB によってデータベースの作成に関する情報が画面に出力されるので、処理の経過を確認できます。 画面出力の例については、次のセクションを参照してください。 たとえば、Windows では次のようにして `mysqld-max.exe' を起動することにより、MySQL サーバはコンソールを閉じなくなります。

 
your-path-to-mysqld\mysqld-max --console

Windows では、`my.cnf' または `my.ini' をどこに配置すればいいでしょうか。 Windows での規則は次のとおりです。

Unix では、どこでオプションを指定すればいいでしょうか。 Unix では、`mysqld' が次のファイル(存在する場合)から次の順序でオプションを読み取ります。

`COMPILATION_DATADIR' は MySQL データディレクトリで、`mysqld' がコンパイルされたときに ./configure オプションとして指定されたものです(一般にはバイナリインストール用の `/usr/local/mysql/data'、またはソースインストール用の`/usr/local/var')。

`mysqld' がその `my.cnf' または `my.ini' をどこから読み取るかがわからない場合は、サーバへの最初のコマンドラインオプションとしてパスを指定できます(mysqld --defaults-file=your_path_to_my_cnf)。

InnoDB は、データファイルへのディレクトリパスを決定する場合に、innodb_data_home_dir に定義されたパスのテキストを innodb_data_file_path 内のデータファイル名またはパスのテキストと結合し、必要に応じて間にスラッシュまたはバックスラッシュを挿入します。`my.cnf' でキーワード innodb_data_home_dir がまったく指定されていない場合は、MySQL の datadir を意味する 'ドット' ディレクトリ `./' がデフォルトで使用されます。

高度な `my.cnf' の例。2 GB の RAM と 3 つの 60 GB ハードディスクを搭載した Linux コンピュータを使用しているとします。ハードディスクのディレクトリパスは、それぞれ `/'、`/dr2'、`/dr3' です。次に示すのは、InnoDB の `my.cnf' における設定パラメータの例です。

注意: ディレクトリは InnoDB によって作成されないので、各自で作成する必要があります。データおよびロググループのホームディレクトリを作成するには、Unix または MS-DOS の mkdir コマンドを使用します。

 
[mysqld]
# You can write your other MySQL server options here
# ...
innodb_data_home_dir =
#                                  Datafiles must be able to
#                                  hold your data and indexes
innodb_data_file_path = /ibdata/ibdata1:2000M;/dr2/ibdata/ibdata2:2000M:autoextend
#                                  Set buffer pool size to
#                                  50 - 80 % of your computer's
#                                  memory, but make sure on Linux
#                                  x86 total memory usage is
#                                  < 2 GB
innodb_buffer_pool_size=1G
innodb_additional_mem_pool_size=20M
innodb_log_group_home_dir = /dr3/iblogs
#                                  .._log_arch_dir must be the same
#                                  as .._log_group_home_dir
innodb_log_arch_dir = /dr3/iblogs
innodb_log_files_in_group=3
#                                  Set the log file size to about
#                                  15 % of the buffer pool size
innodb_log_file_size=150M
innodb_log_buffer_size=8M
#                                  Set ..flush_log_at_trx_commit to
#                                  0 if you can afford losing
#                                  some last transactions 
innodb_flush_log_at_trx_commit=1
innodb_lock_wait_timeout=50
#innodb_flush_method=fdatasync
#innodb_thread_concurrency=5

2 つのデータファイルを異なるディスクに配置したことに注意してください。 InnoDB は、データファイルによって形成されるテーブルスペースをボトムアップ式に埋めていきます。場合によっては、すべてのデータを同じ物理ディスクに配置しない方がパフォーマンスが良くなります。ログファイルをデータとは別のディスクに配置すると、ほとんどの場合パフォーマンスは良くなります。 ローデバイス をデータファイルとして使用することもできます。一部の Unix では、この方法で I/O の処理速度が向上します。`my.cnf' でこのようなデータファイルを指定する方法については、マニュアルで 「7.5.13.1 ディスク I/O」 に関するセクションを参照してください。

警告: Linux x86 では、メモリ使用率の設定を高くし過ぎないように注意してください。glibc はプロセスヒープがスレッドスタックよりも大きくなることを許可しており、その場合にサーバがクラッシュします。次の計算式を見てください。

 
innodb_buffer_pool_size + key_buffer_size +
max_connections * (sort_buffer_size + read_buffer_size) + max_connections * 2 MB

この値が、2 GB に近いか、2 GB を超えていると危険です。各スレッドはスタックを使用し(通常は 2 MB。ただし MySQL AB バイナリでは 256 KB のみ)、最悪の場合、sort_buffer_size + read_buffer_size の大きさの追加メモリも使用します。

他の `mysqld' サーバパラメータはどのように調整すればいいでしょうか。: ほとんどのユーザに適した一般的な値は次のとおりです。

 
skip-locking
max_connections=200
read_buffer_size=1M
sort_buffer_size=1M
#                                  Set key_buffer_size to 5 - 50%
#                                  of your RAM depending on how
#                                  much you use MyISAM tables, but
#                                  keep key_buffer_size + InnoDB
#                                  buffer pool size < 80% of
#                                  your RAM
key_buffer_size=...

注意: 4.0 より前のバージョンでは、一部のパラメータを set-variable = innodb... = 123 のように指定する必要があります。

各設定パラメータの意味は次のとおりです。

オプション 説明
innodb_file_per_table 4.1.1 より利用可能。このオプションによって、InnoDB は作成された各テーブルを独自の `.ibd' ファイルに格納するようになる。複数のテーブルスペースに関するセクションを参照。
innodb_data_home_dir ディレクトリパスの中の、すべての InnoDB データファイルに共通な部分。`my.cnf' でこのオプションを指定しなかった場合のデフォルトは、MySQL の datadir。このオプションには空の文字列も指定できる。その場合、innodb_data_file_path に絶対ファイルパスを指定できる。
innodb_data_file_path 個々のデータファイルへのパスとそのサイズ。各データファイルへのフルディレクトリパスは、ここで指定したパスに innodb_data_home_dir を連結することで取得できる。ファイルサイズはメガバイトで指定されるため、上記のようにサイズの後に 'M' が付加されている。InnoDB は 'G' という略称も認識する。1 G は 1,024 MB を意味する。3.23.44 より、大きなファイルをサポートするオペレーティングシステムで 4 GB を超えるファイルサイズも設定できるようになった。一部のオペレーティング システムでは、ファイルを 2 GB 未満にする必要がある。4.0 より、innodb_data_file_path を指定しない場合のデフォルトの動作として、10 MB の自動拡張データファイル `ibdata1' が作成される。ファイルの合計サイズは、10 MB 以上でなければならない。
innodb_mirrored_log_groups データベースのために保持しておくロググループのコピーの数。現時点では 1 に設定する必要がある。
innodb_log_group_home_dir InnoDB ログファイルへのディレクトリパス。`my.cnf' でこのオプションを指定しなかった場合は、デフォルトで MySQL の datadir が設定される。
innodb_log_files_in_group ロググループ内のログファイルの数。InnoDB はこれらのログファイルに循環的に書き込みを行う。このパラメータの推奨値とデフォルト値は共に 2。
innodb_log_file_size ロググループ内の各ログファイルのサイズ(メガバイト)。実際的な値の範囲は、1M から、下で指定するバッファプールのサイズの 1/n まで(n はグループ内のログファイルの数)。この値が大きいほど、バッファプールで必要となるチェックポイントフラッシュの回数が減るため、ディスク I/O が削減される。ただし、ログファイルが大きいと、クラッシュした場合のリカバリに時間がかかる。32 ビットコンピュータでは、ログファイルの合計サイズを 4 GB 未満にする必要がある。デフォルトは 5M。
innodb_log_buffer_size InnoDB がディスク上のログファイルにログを書き出すために使用するバッファのサイズ。実際的な値は 1M 〜 8M。ログバッファを大きくすると、トランザクションコミットまでディスクにログを書き出すことなく大きなトランザクションを実行できる。大きなトランザクションがある場合は、このようにログバッファを大きくすることでディスク I/O を削減できる。
innodb_flush_log_at_trx_commit 通常、このパラメータは 1 に設定する。これによって、トランザクションコミット時にログがディスクにフラッシュされ、トランザクションによる変更が確定されてデータベースクラッシュを免れる。このような安全性を必要とせず、かつ小さなトランザクションを実行している場合は、このオプションを 0 または 2 に設定してログへのディスク I/O を削減できる。値 0 を指定すると、ログファイルへのログの書き込み、およびディスクへのログファイルのフラッシュが1 秒に約1 回しか行われなくなる。値 2 を指定すると、ログファイルへのログの書き込みはコミットのたびに行われるが、ディスクへのログファイルのフラッシュは 1 秒に約 1 回しか行われなくなる。MySQL-4.0.13 よりデフォルト値が 0 から 1 に変更された。
innodb_log_arch_dir ログのアーカイブを使用する場合に、いっぱいになったログファイルがアーカイブされるディレクトリ。現時点では、このパラメータを innodb_log_group_home_dir と同じ値に設定する必要がある。
innodb_log_archive 現時点では、このパラメータを 0 に設定する必要がある。バックアップからのリカバリは MySQL が独自のログファイルを使って行うため、現時点では InnoDB のログファイルをアーカイブする必要はない。
innodb_buffer_pool_size InnoDB が、そのテーブルのデータやインデックスをキャッシュするために使用するメモリバッファのサイズ。この値が大きいほど、テーブル内のデータへのアクセスに必要なディスク I/O が少なくなる。データベース専用サーバでは、このパラメータをマシンの物理メモリの 80% にまで設定できる。ただし、物理メモリの競合によってオペレーティングシステムでページングが発生する可能性があるため、あまり大きな値は設定しないようにする。
innodb_buffer_pool_awe_mem_mb 32 ビット版 Windows の AWE メモリに配置されるバッファプールのサイズ(MB)。4.1.0 から利用可能で、32 ビット版 Windows にのみ関係する。使用する 32 ビット版 Windows オペレーティングシステムが、Address Windowing Extensions(AWE)と呼ばれる 4 GB を超えるメモリをサポートしている場合は、このパラメータを使用して InnoDB バッファプールを AWE 物理メモリに割り当てることができる。指定可能な最大値は、64000。このパラメータを指定した場合、innodb_buffer_pool_size は mysqld の 32 ビットアドレス空間におけるウィンドウとなる(このアドレス空間で InnoDB が AWE メモリをマップする)。その場合の innodb_buffer_pool_size に適したサイズは 500M。
innodb_additional_mem_pool_size InnoDB がデータディクショナリの情報とその他の内部データ構造を格納するために使用するメモリプールのサイズ。このパラメータの実際的な値は 2M であるが、アプリケーションで使用するテーブルの数が多いほど、この値を大きくする必要がある。InnoDB は、このプールのメモリを使い果たすと、オペレーティングシステムからメモリを割り当てるようになり、MySQL エラーログに警告メッセージを書き込む。
innodb_file_io_threads InnoDB におけるファイル I/O スレッドの数。通常、この値は 4 にする必要があるが、Windows ではこれより大きな数を指定するとディスク I/O の面で有利になる場合がある。
innodb_lock_wait_timeout ロック待機の状態になった InnoDB トランザクションがロールバックされるまでのタイムアウト時間(秒)。InnoDB は、そのロックテーブルでトランザクションのデッドロックを自動的に検出し、そのトランザクションをロールバックする。LOCK TABLES コマンドを使用するか、または同じトランザクションで InnoDB 以外のトランザクションセーフのストレージエンジンを使用すると、InnoDB が検出できないデッドロックが発生することがある。タイムアウトは、このような状況の解決に役立つ。
innodb_flush_method 3.23.40 より使用可能。デフォルト値は fdatasync。これ以外に、O_DSYNC を指定できる。
innodb_force_recovery 警告: このオプションは、破損したデータベースからテーブルをダンプする必要がある緊急事態でのみ定義する必要がある。指定可能な値は 1 〜 6。それぞれの値の意味については、この後の「強制的なリカバリ」を参照。InnoDB では、安全対策として、このオプションが 0 より大きいときはユーザがデータを変更できないようになっている。このオプションは、バージョン 3.23.44 より使用可能。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.5.4 InnoDB テーブルスペースの作成

MySQL がすでにインストールされ、`my.cnf' の編集も終わって必要な InnoDB 設定パラメータが設定されているとします。 MySQL を起動する前に、InnoDB データファイルとログファイル用に指定したディレクトリが存在すること、およびそれらのディレクトリへのアクセス権があることを確認する必要があります。InnoDB によって作成されるのはファイルのみで、ディレクトリは作成されません。データファイルとログファイルを保存できるだけの十分なディスク領域があることも確認してください。

MySQL を起動すると、InnoDB はデータファイルとログファイルの作成を開始し、次のようなメッセージを出力します。

 
~/mysqlm/sql > mysqld
InnoDB: The first specified datafile /home/heikki/data/ibdata1
did not exist:
InnoDB: a new database to be created!
InnoDB: Setting file /home/heikki/data/ibdata1 size to 134217728
InnoDB: Database physically writes the file full: wait...
InnoDB: datafile /home/heikki/data/ibdata2 did not exist:
new to be created
InnoDB: Setting file /home/heikki/data/ibdata2 size to 262144000
InnoDB: Database physically writes the file full: wait...
InnoDB: Log file /home/heikki/data/logs/ib_logfile0 did not exist:
new to be created
InnoDB: Setting log file /home/heikki/data/logs/ib_logfile0 size to 5242880
InnoDB: Log file /home/heikki/data/logs/ib_logfile1 did not exist:
new to be created
InnoDB: Setting log file /home/heikki/data/logs/ib_logfile1 size to 5242880
InnoDB: Log file /home/heikki/data/logs/ib_logfile2 did not exist:
new to be created
InnoDB: Setting log file /home/heikki/data/logs/ib_logfile2 size to 5242880
InnoDB: Started
mysqld: ready for connections

これで、新しい InnoDB データベースが作成されました。mysql などの通常使用する MySQL クライアントプログラムで MySQL サーバに接続できます。 `mysqladmin shutdown' で MySQL サーバをシャットダウンすると、InnoDB から次のようなメッセージが出力されます

 
010321 18:33:34  mysqld: Normal shutdown
010321 18:33:34  mysqld: Shutdown Complete
InnoDB: Starting shutdown...
InnoDB: Shutdown completed

これで、データファイルとログのディレクトリを参照できるようになり、作成したファイルを確認できます。ログディレクトリには、`ib_arch_log_0000000000' という名前の小さなファイルも作成されます。これは、データベース作成時に作成されたファイルで、その後に InnoDB がログのアーカイブをオフに切り替えています。 MySQL を再び起動すると、次のようなメッセージが出力されます。

 
~/mysqlm/sql > mysqld
InnoDB: Started
mysqld: ready for connections

7.5.4.1 データベース作成時に問題が生じた場合   


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.5.4.1 データベース作成時に問題が生じた場合

InnoDB がファイル操作中にオペレーティングシステムエラーを出力した場合、通常は次のいずれかが原因です。

InnoDB データベースの作成で問題が生じた場合は、InnoDB が作成したすべてのファイルを削除する必要があります。つまり、MySQL データベースディレクトリから、すべてのデータファイル、すべてのログファイル、アーカイブされた小さなログファイルを削除し、InnoDB テーブルを作成した場合は、これらのテーブルに対応する `.frm' ファイルも削除します。これで、InnoDB データベースを再び作成することができます。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.5.5 InnoDB テーブルの作成

mysql test で MySQL クライアントを起動したとします。 InnoDB 形式のテーブルを作成するには、テーブルを作成する SQL コマンドで、TYPE = InnoDB を指定する必要があります。

 
CREATE TABLE CUSTOMER (A INT, B CHAR (20), INDEX (A)) TYPE = InnoDB;

この SQL コマンドによって、`my.cnf' に指定したデータファイルから成る InnoDB テーブルスペースに、テーブルおよびカラム A のインデックスが作成されます。さらに MySQL によって、MySQL データベースディレクトリ `test' に `CUSTOMER.frm' ファイルが作成されます。 内部では、InnoDB が独自のデータディクショナリに 'test/CUSTOMER' テーブルのエントリを追加します。したがって、MySQL の別のデータベースに同じ CUSTOMER という名前のテーブルを作成しても、InnoDB 内部でテーブル名が衝突することはありません。

TYPE = InnoDB で作成した任意のテーブルに対して MySQL のテーブルステータスコマンドを発行することで、InnoDB テーブルスペースの空き容量を照会できます。テーブルスペースの空き容量は、SHOW の出力のテーブルコメントセクションに表示されます。次に例を示します。

 
SHOW TABLE STATUS FROM test LIKE 'CUSTOMER';

SHOW が InnoDB テーブルについて出力する統計情報は概算であることに注意してください。これらの情報は、SQL 文解析の最適化で使用されます。ただし、テーブルとインデックスに予約されているサイズ(バイト単位)は正確です。

7.5.5.1 MyISAM テーブルから InnoDB への変換   
7.5.5.2 FOREIGN KEY 制約   
7.5.5.3 複数テーブルスペース - 各テーブルを独自の .ibd ファイルに入れる   


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.5.5.1 MyISAM テーブルから InnoDB への変換

InnoDB には、インデックスを別途作成するための特別な最適化機能がありません。 このため、テーブルをエクスポートしてインポートし、その後にインデックスを作成しなおしても意味がありません。 テーブルを最も速く InnoDB に変換するには、InnoDB テーブルに直接データを挿入します。つまり、ALTER TABLE ... TYPE=INNODB を使用するか、あるいは同じ定義で空の InnoDB テーブルを作成し、INSERT INTO ... SELECT * FROM ... でレコードを挿入します。

挿入処理を管理しやすくするために、大きなテーブルは分割して挿入するとよいでしょう。

 
INSERT INTO newtable SELECT * FROM oldtable
   WHERE yourkey > something AND yourkey <= somethingelse;

すべてのデータを挿入した後に、テーブル名を変更することができます。

大きなテーブルを変換する際には、InnoDB のバッファプールサイズを大きくして、ディスク I/O を削減する必要があります。ただし、物理メモリの 80% を超えないようにしてください。 InnoDB のログファイルおよびログバッファも大きなサイズに設定します。

テーブルスペースが不足していないことを確認します。InnoDB テーブルは、MyISAM テーブルよりも多くの領域を使用します。ALTER TABLE で領域が足りなくなると、ロールバックが実行されます。ロールバックがディスクバウンドすると、完了までに数時間を要する可能性があります。 挿入の際は、InnoDB が挿入バッファを使用してセカンダリインデックスレコードをまとめてインデックスにマージします。これによって、ディスク I/O が大幅に削減されます。ロールバックではこのようなメカニズムが使用されないため、挿入の 30 倍の時間がかかる場合があります。

ロールバックが暴走した場合は、データベースに貴重なデータがなければ、膨大なディスク I/O の完了を待つよりも、データベースプロセスを強制終了し、すべての InnoDB データファイルとログファイル、および InnoDB テーブルの `.frm' ファイルを削除したうえで、再度ジョブを実行した方が得策です。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.5.5.2 FOREIGN KEY 制約

バージョン 3.23.43b より、InnoDB に外部キー制約が装備されるようになりました。 InnoDB は、データの完全性を守るためにユーザが外部キー制約を定義できるようにした最初の MySQL テーブル型です。

InnoDB における外部キー制約定義の構文は次のとおりです。
 
[CONSTRAINT [symbol]] FOREIGN KEY (index_col_name, ...)
                  REFERENCES table_name (index_col_name, ...)
                  [ON DELETE {CASCADE | SET NULL | NO ACTION
                              | RESTRICT}]
                  [ON UPDATE {CASCADE | SET NULL | NO ACTION
                              | RESTRICT}]
どちらのテーブルも InnoDB 型でなければなりません。テーブル内には、外部キーカラムが最初のカラムとして同じ順序で列挙されているインデックスが必要です。また、参照テーブル内には、参照カラムが最初のカラムとして同じ順序で列挙されているインデックスが必要です。InnoDB は、外部キーまたは参照キーに対して自動的にインデックスを作成しません。したがって、ユーザが明示的にインデックスを作成する必要があります。外部キーのチェックを高速化し、テーブルスキャンを不要にするには、インデックスが必要です。

外部キーと参照キーの対応するカラムは、型を変換しなくても比較できるように、InnoDB 内部で同じデータ型にする必要があります。 整数型については、サイズと符号の有無が同じでなければなりません。 文字列型の長さは同じでなくてもかまいません。 SET NULL アクションを指定する場合は、子テーブル内のカラムを NOT NULL と宣言していないことを確認してください。

MySQL が CREATE TABLE ステートメントでエラー番号 1005 を返し、エラーメッセージ文字列に errno 150 が示されている場合は、外部キー制約が正しく作成されなかったためにテーブルの作成が失敗しています。 同様に、ALTER TABLE が失敗して errno 150 が示された場合は、変更されたテーブルに対して外部キー定義が誤って作成されています。バージョン 4.0.13 より、SHOW INNODB STATUS を使用して、サーバで最後に発生した InnoDB 外部キーエラーの詳細な説明を参照できるようになりました。

バージョン 3.23.50 より、InnoDB は NULL カラムを含んでいる外部キーまたは参照キー値で外部キー制約をチェックしなくなりました。

標準 SQL からの逸脱: 親テーブルに同じ参照キー値を持つ複数のレコードがある場合、InnoDB の外部キーチェックでは、同じキー値を持つ親レコードが他に存在しないものとして処理が行われます。たとえば、RESTRICT 型制約を定義し、かつ複数の親レコードを持つ子レコードが存在する場合、InnoDB はこれらの親レコードの削除を禁止します。

バージョン 3.23.50 より、ON DELETE CASCADE 節または ON DELETE SET NULL 節を外部キー制約に付けることもできるようになりました。対応する ON UPDATE オプションは、4.0.8 より利用可能です。ON DELETE CASCADE が指定されている場合に親テーブル内のレコードが削除されると、InnoDB は子テーブル内で親レコード内の参照キー値と等しい外部キー値を持つすべてのレコードを自動的に削除します。ON DELETE SET NULL が指定されている場合は、子レコードが自動的に更新されて、外部キー内のカラムが SQL の NULL 値に設定されます。

標準 SQL からの逸脱: ON UPDATE CASCADE または ON UPDATE SET NULL は、カスケード中にすでに更新したテーブルを繰り返して更新する場合に、RESTRICT のように動作します。これは、カスケードされた更新から生じる無限ループを防ぐためです。一方、自己参照型の ON DELETE SET NULL が 4.0.13 から動作するようになりました。 自己参照型の ON DELETE CASCADE は、以前から動作していました。

次に例を示します。
 
CREATE TABLE parent(id INT NOT NULL, PRIMARY KEY (id)) TYPE=INNODB;
CREATE TABLE child(id INT, parent_id INT, INDEX par_ind (parent_id),
             FOREIGN KEY (parent_id) REFERENCES parent(id)
             ON DELETE SET NULL
) TYPE=INNODB;

次に示すのは複雑な例です。
 
CREATE TABLE product (category INT NOT NULL, id INT NOT NULL,
                      price DECIMAL,
                      PRIMARY KEY(category, id)) TYPE=INNODB;
CREATE TABLE customer (id INT NOT NULL,
                      PRIMARY KEY (id)) TYPE=INNODB;
CREATE TABLE product_order (no INT NOT NULL AUTO_INCREMENT,
                      product_category INT NOT NULL,
                      product_id INT NOT NULL,
                      customer_id INT NOT NULL,
                      PRIMARY KEY(no),
                      INDEX (product_category, product_id),
                      FOREIGN KEY (product_category, product_id)
                        REFERENCES product(category, id)
                        ON UPDATE CASCADE ON DELETE RESTRICT,
                      INDEX (customer_id),
                      FOREIGN KEY (customer_id)
                        REFERENCES customer(id)) TYPE=INNODB;

バージョン 3.23.50 より、InnoDB では次のステートメントによって新しい外部キー制約をテーブルに追加できるようになりました。
 
ALTER TABLE yourtablename
ADD [CONSTRAINT [symbol]] FOREIGN KEY (...) REFERENCES anothertablename(...)
[on_delete_and_on_update_actions]
ただし、必要なインデックスを先に作成することを忘れないでください

バージョン 4.0.13 より、InnoDB が次のステートメントをサポートするようになりました。
 
ALTER TABLE yourtablename DROP FOREIGN KEY internally_generated_foreign_key_id
外部キーを破棄する場合は、SHOW CREATE TABLE を使って、内部で生成された外部キー ID を確認する必要があります。 InnoDB が 3.23.50 より前のバージョンである場合は、外部キー制約を持つテーブルまたは外部キー制約で参照されるテーブルに関連して ALTER TABLE または CREATE INDEX を使用しないでください。ALTER TABLE を実行すると、テーブルに定義されているすべての外部キー制約が削除されます。ALTER TABLE は、参照テーブルにも使用しないでください。ただし、スキーマを変更する場合は DROP TABLE および CREATE TABLE を使用します。MySQL は、ALTER TABLE を実行するときに内部的に RENAME TABLE を使用する場合があります。この場合、テーブルを参照する外部キー制約で混乱が生じます。 CREATE INDEX ステートメントは、MySQL では ALTER TABLE として処理されるため、このステートメントにもこれらの制約が適用されます。

InnoDB は、外部キーチェックを実行する際に、参照する子レコードまたは親レコードに対して共有行レベルロックを設定します。 InnoDB は、外部キー制約を即座にチェックします。チェックがトランザクションコミットまで延期されることはありません。

外部キー制約を、たとえば LOAD DATA 処理の間だけ無視する場合は、SET FOREIGN_KEY_CHECKS=0 を実行します。

InnoDB では、外部キー制約によって参照されているテーブルでも破棄できます。この場合、その制約が壊れることになります。テーブルを破棄すると、その作成ステートメントで定義された制約も破棄されます。

破棄されたテーブルを再作成する場合は、そのテーブルを参照する外部キー制約に沿った定義をテーブル内に設定する必要があります。すでに説明したように、このテーブルには、正しい名前と型を持つカラム、および参照キー上のインデックスが必要です。 これらの条件が満たされていないと、MySQL からエラー番号 1005 が返され、エラーメッセージ文字列に errno 150 が示されます。

バージョン 3.23.50 より、次のステートメントを呼び出すと、InnoDB からテーブルの外部キー定義が返されるようになりました。
 
SHOW CREATE TABLE yourtablename
また、`mysqldump' によってテーブルの正しい定義と共に外部キーがダンプファイルに出力されます。

また、次のステートメントでテーブル T の外部キー制約も列挙できます。
 
SHOW TABLE STATUS FROM yourdatabasename LIKE 'T'
外部キー制約は、出力のテーブルコメントに列挙されます。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.5.5.3 複数テーブルスペース - 各テーブルを独自の .ibd ファイルに入れる

重要: InnoDB-4.1.1 にアップグレードした後に、ダウングレードすることはできません。それは、InnoDB の以前のバージョンが複数のテーブルスペースを認識しないためです。

MySQL-4.1.1 より、各 InnoDB テーブルとそのインデックスを、そのテーブル独自のファイルに格納できるようになりました。各テーブルが独自のテーブルスペースに格納されることから、この機能は複数テーブルスペースと呼ばれます。

この機能を有効にするには、`my.cnf' の [mysqld] セクションに次の行を追加します。
 
innodb_file_per_table
これによって InnoDB は、各テーブルが属しているデータベースディレクトリ内にあるテーブル固有の `tablename.ibd' ファイルに、それぞれのテーブルを格納します。これは MyISAM の動作と似ていますが、MyISAM ではテーブルがデータファイル `tablename.MYD' とインデックスファイル `tablename.MYI' に分けられます。InnoDB の場合は、データとインデックスの両方が `.ibd' ファイルに格納されます。

`my.cnf' から行 innodb_file_per_table を削除すると、InnoDB によって再び `ibdata' ファイル内にテーブルが作成されます。4.1.1 以降のバージョンへアップグレードする前に `ibdata' ファイルに格納されていた古いテーブルはそのまま残され、`.ibd' ファイルに変換されることはありません。

InnoDB にはシステムテーブルスペースが必要で、`.ibd' ファイルだけでは不十分です。 システムテーブルスペースは、これまで使われていた `ibdata' ファイルで構成されます。InnoDB は、内部データディクショナリと UNDO ログをシステムテーブルスペースに配置します。

MyISAM テーブルとは異なり、.ibd ファイルは自由に移動できません。これは、テーブル定義が InnoDB システムテーブルスペースに格納されているためと、InnoDB でトランザクション ID とログシーケンス番号の整合性を維持する必要があるためです。

従来の RENAME コマンドを使って、`.ibd' ファイルと関連テーブルを、あるデータベースから同じ MySQL/InnoDB インストール内にある別のデータベースに移すことができます。
 
RENAME TABLE olddatabasename.tablename TO newdatabasename.tablename;

同じ MySQL/InnoDB インストールから取得した `.ibd' ファイルのクリーンバックアップがある場合は、次のコマンドでそのバックアップを InnoDB データベースにリストアできます。
 
ALTER TABLE tablename DISCARD TABLESPACE; /* CAUTION: 現在の .ibd ファイルを削除します! */
<バックアップした .ibd ファイルを適切な場所に置きます>
ALTER TABLE tablename IMPORT TABLESPACE;
ここでのクリーンとは、次のことを意味しています。

このような `.ibd' ファイルのクリーンバックアップは、次の方法で作成できます。

クリーンな `.ibd' ファイルを作成するもう 1 つの方法(有償)があります。

TODO には、クリーンな `.ibd' ファイルも別の MySQL/InnoDB に移動できるようにすることが挙げられています。そのためには、`.ibd' ファイル内でトランザクション ID とログシーケンス番号をリセットすることが必要になります。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.5.6 InnoDB データファイルとログファイルの追加と削除

バージョン 3.23.50 および 4.0.2 より、InnoDB の最後のデータファイルに autoextend を指定できるようになりました。あるいは、追加のデータファイルを指定してテーブルスペースを拡大することができます。そのためには、MySQL サーバをシャットダウンし、`my.cnf' ファイルで innodb_data_file_path末尾に新しいデータファイルを追加し、MySQL サーバを再起動します。

現時点では、InnoDB からデータファイルを削除することはできません。データベースのサイズを小さくするには、`mysqldump' ですべてのテーブルをダンプし、新しいデータベースを作成し、そのデータベースにテーブルをインポートする必要があります。

InnoDB ログファイルの数またはサイズを変更する場合は、MySQL をシャットダウンし、エラーなくシャットダウンすることを確認する必要があります。 その後に、シャットダウンで問題が発生した場合に備えて、古いログファイルを安全な場所にコピーします。これらはデータベースをリカバリする際に必要となります。古いログファイルをログファイルディレクトリから削除し、`my.cnf' を編集してから MySQL を再び起動します。起動時に、InnoDB から新しいログファイルを作成していることが通知されます。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.5.7 InnoDB データベースのバックアップとリカバリ

安全なデータベース管理の秘訣は、定期的にバックアップを取ることです。

InnoDB ホットバックアップは、稼働中の InnoDB データベースをバックアップするためのオンラインバックアップツールです。InnoDB ホットバックアップでは、データベースをシャットダウンする必要がなく、ロックが設定されたり、通常のデータベース処理が妨害されたりすることもありません。InnoDB ホットバックアップは、追加で導入する有償のツールで、標準の MySQL ディストリビューションには含まれていません。詳細情報とスクリーンショットについては、InnoDB ホットバックアップのホームページ(http://www.innodb.com/manual.php )を参照してください。

MySQL サーバをシャットダウンできる場合は、データベースの 'バイナリ' バックアップを取るために次の作業を行う必要があります。

上記のバイナリバックアップに加えて、`mysqldump' を使って定期的にテーブルのダンプを取るようにしてください。その理由は、バイナリファイルが気付かないうちに壊れる可能性があるためです。ダンプされたテーブルはテキストファイルに格納されます。これらは人間による解読が可能で、データベースバイナリファイルよりもはるかに単純です。ダンプされたファイルではテーブルの破損を容易に確認できます。また、このファイルの形式は単純であるため、重大なテーブルの破損が起こる確率も低くなります。

データベースのバイナリバックアップと同時にダンプを取ることをお勧めします。すべてのテーブルのスナップショットを矛盾のない状態でダンプするには、すべてのクライアントをデータベースからシャットアウトする必要があります。その後にバイナリバックアップを取れば、データベースの矛盾のないスナップショットを 2 つの形式で保持することになります。

上記のバイナリバックアップから InnoDB データベースをリカバリできるようにするには、MySQL の一般的なログをオンにして MySQL データベースを実行する必要があります。ここでの一般的なログとは、InnoDB ログとは関係のない MySQL サーバのログメカニズムを意味します。

MySQL サーバプロセスのクラッシュからリカバリする場合に必要な作業は、そのプロセスの再起動だけです。InnoDB は自動的にログをチェックし、現時点までのデータベースのロールフォワードを実行します。InnoDB は、クラッシュ時にコミットされていなかったトランザクションを自動的にロールバックします。リカバリの間、InnoDB は次のようなメッセージを出力します。

 
~/mysqlm/sql > mysqld
InnoDB: Database was not shut down normally.
InnoDB: Starting recovery from log files...
InnoDB: Starting log scan based on checkpoint at
InnoDB: log sequence number 0 13674004
InnoDB: Doing recovery: scanned up to log sequence number 0 13739520
InnoDB: Doing recovery: scanned up to log sequence number 0 13805056
InnoDB: Doing recovery: scanned up to log sequence number 0 13870592
InnoDB: Doing recovery: scanned up to log sequence number 0 13936128
...
InnoDB: Doing recovery: scanned up to log sequence number 0 20555264
InnoDB: Doing recovery: scanned up to log sequence number 0 20620800
InnoDB: Doing recovery: scanned up to log sequence number 0 20664692
InnoDB: 1 uncommitted transaction(s) which must be rolled back
InnoDB: Starting rollback of uncommitted transactions
InnoDB: Rolling back trx no 16745
InnoDB: Rolling back of trx no 16745 completed
InnoDB: Rollback of uncommitted transactions completed
InnoDB: Starting an apply batch of log records to the database...
InnoDB: Apply batch completed
InnoDB: Started
mysqld: ready for connections

データベースの破損またはディスク障害が発生した場合は、バックアップからリカバリを実行する必要があります。データベースが壊れた場合は、まず壊れていないバックアップを探します。MySQL のマニュアルに従って、MySQL の一般ログファイルからのリカバリを実行します。

7.5.7.1 強制的なリカバリ   
7.5.7.2 チェックポイント   


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top ] [Contents ] [Index] [ ? ]

7.5.7.1 強制的なリカバリ

データベースページが壊れた場合は、SELECT INTO OUTFILE を使ってデータベースからテーブルをダンプできます。通常は、ほとんどのデータが損傷を受けず正常な状態です。ところが、破損が原因で SELECT * FROM table や InnoDB のバックグラウンド処理がクラッシュまたはアサートしたり、InnoDB のロールフォワードリカバリさえもクラッシュすることがあります。InnoDB のバージョン 3.23.44 より、InnoDB を強制的に起動することのできるオプションが `my.cnf' に追加されました。また、テーブルをダンプできるように、バックグラウンド処理が実行されないようにすることも可能となりました。たとえば、`my.cnf' で
 
innodb_force_recovery = 4
を設定することができます。

innodb_force_recovery の選択肢は下に挙げています。 データベースには、これらのオプションを別の用途で使用しないでください。 InnoDB では、安全対策として、このオプションが 0 より大きいときはユーザが INSERTUPDATE、または DELETE を実行できないようになっています。

バージョン 3.23.53 および 4.0.4 より、強制リカバリが使用される場合でも、テーブルの DROP または CREATE を実行することができます。ロールバックでクラッシュを引き起こしているテーブルが特定できれば、そのテーブルを破棄できます。 また、問題のある大量インポートまたは ALTER TABLE が原因で暴走したロールバックも、この方法で停止できます。 mysqld プロセスを強制終了し、`my.cnf' のオプション innodb_force_recovery=3 を使用することで、ロールバックせずにデータベースを正常な状態に戻すことができます。 その後に、ロールバックが暴走する原因となったテーブルを DR