[ < ] [ > ]   [ << ] [ 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 を使用することで、ロールバックせずにデータベースを正常な状態に戻すことができます。 その後に、ロールバックが暴走する原因となったテーブルを DROP で破棄します。

下に列挙されている各オプションでは、その番号が大きいものがより小さい番号の対策をすべて盛り込んでいます。悪くてもオプション 4 でテーブルをダンプできれば、個々のページが破損しても一部のデータが失われるだけなので比較的安全です。オプション 6 にはより劇的な影響力があります。データベースページが古い状態のまま残るため、B ツリーやその他のデータベース構造へさらに破損が及ぶ可能性があるからです。


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

7.5.7.2 チェックポイント

InnoDB には、ファジーチェックポイントと呼ばれるチェックポイントメカニズムが実装されています。InnoDB は、変更されたデータベースページを小規模なバッチ単位でバッファプールからフラッシュします。バッファプールを 1 回のバッチでフラッシュする必要はありません。実際にこれを行うと、ユーザの SQL ステートメントの処理が一時的に停止します。

クラッシュリカバリの際に、InnoDB はログファイルに書き込まれたチェックポイントラベルを検索します。InnoDB は、このラベルより前に実行されたデータベースへの変更が、データベースのディスクイメージにすでに反映されていることを認識しています。 次に InnoDB は、ログファイルでこのチェックポイント以降をスキャンし、ログに記録された変更をデータベースに適用します。

InnoDB はログファイルへの書き込みを循環的に行います。 InnoDB によるリカバリが必要となった場合は、バッファプール内のデータベースページとディスク上のイメージの不一致を引き起こしている全てのコミット済みの変更を、ログファイルから取得できなければなりません。つまり、InnoDB は、ログファイルを循環的に再使用する際に、再使用しようとするログファイルに記録された変更が、ディスク上のデータベースページのイメージにすでに反映されていることを確認する必要があります。そのために InnoDB はチェックポイントを作成する必要があり、それには変更されたデータベースページをディスクにフラッシュする処理が伴います。

これらのことから、ログファイルを大きくしておけば、チェックポイントを実行する際のディスク I/O を削減できると言えます。ログファイルの合計サイズを、バッファプールのサイズ以上に設定することは理に適っています。 ログファイルを大きくした場合の難点として、データベースに適用するログの量が増えるために、クラッシュリカバリに時間がかかるおそれがあります。


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

7.5.8 InnoDB データベースを別のマシンに移動する

Windows では、InnoDB がデータベース名とテーブル名を内部的に小文字で格納します。バイナリ形式のデータベースを Unix から Windows に、またはその逆に移動するには、すべてのテーブル名とデータベース名を小文字にする必要があります。Unix でこれを簡単に行うには、`my.cnf' の [mysqld] セクションに次の行を追加します。
 
lower_case_table_names=1
これは、テーブルの作成を開始する前に行います。Windows では、デフォルトで 1 に設定されます。

InnoDB のデータファイルとログファイルは、すべてのプラットフォームでバイナリ互換です。ただし、それらのマシンで浮動小数点数の形式が同じであることが必要です。 InnoDB データベースは、すべての関連ファイルをコピーするだけで移動できます。関連ファイルについては、データベースのバックアップに関する前のセクションを参照してください。マシン間で浮動小数点数の形式が異なっていても、テーブル内で FLOAT または DOUBLE データ型を使用していなければ手順は同じです。つまり、関連ファイルをコピーするだけで済みます。浮動小数点数の形式が異なっている場合に、テーブルで浮動小数点データが使用されているときは、`mysqldump' および `mysqlimport' を使用してそれらのテーブルを移動する必要があります。

パフォーマンス上のヒントとして、データをデータベースにインポートするときは、大量のインポートトランザクションによって生成される大きなロールバックセグメントに対応できるだけの十分なテーブルスペースがあると想定して、オートコミットモードをオフにします。 コミットは、テーブル全体またはテーブルのセグメントをインポートした後に実行します。


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

7.5.9 InnoDB トランザクションモデルとロック

InnoDB トランザクションモデルの目標は、マルチバージョニングのデータベースの優れた特性を、従来の 2 相ロックと組み合わせることでした。 InnoDB は、行レベルでロックを行い、デフォルトではクエリを Oracle 式の非ロックの一貫性読み取りとして実行します。 InnoDB のロックテーブルはスペース効率の高い方法で格納されるため、ロックエスカレーションは不要です。一般には、複数のユーザがデータベースのあらゆるレコードまたはレコードのランダムなサブセットをロックすることができ、InnoDB でメモリ不足が発生することもありません。

InnoDB では、すべてのユーザ活動がトランザクションの内部で発生します。MySQL でオートコミットモードが使用されている場合は、各 SQL ステートメントが 1 つのトランザクションとなります。 MySQL は常にオートコミットモードをオンにして新たな接続を開始します。

SET AUTOCOMMIT = 0 でオートコミットモードがオフになると、ユーザが常にトランザクションを開いていると見なされます。このユーザが SQL の COMMIT または ROLLBACK ステートメントを実行すると、現在のトランザクションが終了し、新しいトランザクションが開始されます。どちらのステートメントも、現在のトランザクションで設定されたすべての InnoDB ロックを解除します。COMMIT を実行すると、現在のトランザクションで加えられた変更が確定し、他のユーザが認識できる状態になります。一方、ROLLBACK ステートメントを実行すると、現在のトランザクションによって加えられたすべての変更が取り消されます。

接続に AUTOCOMMIT = 1 が設定されている場合でも、ユーザはトランザクションを実行できます。その場合、START TRANSACTION または BEGIN でトランザクションを開始し、COMMIT または ROLLBACK でトランザクションを終了します。

7.5.9.1 InnoDB と SET ... TRANSACTION ISOLATION LEVEL ...   
7.5.9.2 ロックを取得しない読み取り一貫性   
7.5.9.3 ロックを取得する読み取り SELECT ... FOR UPDATE および SELECT ... LOCK IN SHARE MODE   
7.5.9.4 ネクストキーロック: ファントムの問題の回避   
7.5.9.5 InnoDB で各種 SQL ステートメントによって設定されるロック   
7.5.9.6 デッドロックの検出とロールバック   
7.5.9.7 InnoDB での読み取り一貫性の例   
7.5.9.8 デッドロックの対処法   


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

7.5.9.1 InnoDB と SET ... TRANSACTION ISOLATION LEVEL ...

SQL-92 のトランザクション分離レベルに関する InnoDB のデフォルトは REPEATABLE READ です。 バージョン 4.0.5 より、InnoDB は SQL-92 標準で記述されている 4 種類のトランザクション分離レベルをすべて提供するようになりました。 `my.cnf' の [mysqld] セクションで、すべての接続に対するデフォルトの分離レベルを設定できます。

 
transaction-isolation = {READ-UNCOMMITTED | READ-COMMITTED
                         | REPEATABLE-READ | SERIALIZABLE}

ユーザは、単一セッションの分離レベルまたは新たに接続するすべてのコネクションの分離レベルを、SET TRANSACTION ステートメントで変更できます。その構文は次のとおりです。

 
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL
                       {READ UNCOMMITTED | READ COMMITTED
                        | REPEATABLE READ | SERIALIZABLE}

SQL 構文ではレベル名にハイフンを付けないことに注意してください。

デフォルトの動作として、次の(まだ開始されていない)トランザクションの分離レベルが設定されます。このステートメントに GLOBAL キーワードを使用すると、それ以降に作成されるすべての新しい接続(既存の接続は対象外)に対してグローバルにデフォルトのトランザクションレベルが設定されます。 これを行うには、SUPER 特権が必要です。SESSION キーワードを使用すると、現在の接続で実行されるすべての新しいトランザクションに対してデフォルトのトランザクションレベルが設定されます。どのクライアントも、自由にセッション分離レベル(トランザクションの途中であっても)または次のトランザクションの分離レベルを変更できます。 3.23.50 より前のバージョンでは、InnoDB テーブルに SET TRANSACTION が作用しませんでした。4.0.5 より前のバージョンでは、REPEATABLE READSERIALIZABLE のみが提供されていました。

グローバルおよびセッションのトランザクション分離レベルは、次のステートメントで確認できます。
 
SELECT @@global.tx_isolation;
SELECT @@tx_isolation;

行レベルロックでは、InnoDB がネクストキーロックを使用します。 つまり、インデックスレコードに加えてインデックスレコードの前の "ギャップ" もロックすることで、他のユーザがそのインデックスレコードの直前に挿入できないようにします。ここでいうネクストキーロックとは、インデックスレコードとその前のギャップをロックするロックのことです。 ギャップロックとは、あるインデックスレコードの前のギャップのみをロックするロックです。

InnoDB における各分離レベルの詳細は次のとおりです。


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

7.5.9.2 ロックを取得しない読み取り一貫性

読み取り一貫性とは、InnoDB がそのマルチバージョニング機能を使用して、ある時点でのデータベースのスナップショットをクエリに提示することを意味します。 クエリには、その時点より前にコミットされたトランザクションによる変更のみが示され、その時点より後のトランザクションまたはコミットされていないトランザクションによる変更は示されません。例外として、クエリを発行したトランザクション自体による変更はクエリに示されます。

デフォルトの REPEATABLE READ 分離レベルで実行している場合は、最初の読み取り内容がスナップショトとして保存され、同じトランザクション内のすべての読み取りで、そのスナップショットから内容が読み取られます。より新しい状態に更新するには、現在のトランザクションをコミットし、その後に新たなクエリを発行します。

読み取り一貫性はデフォルトのモードです。このモードでは、InnoDB が SELECT ステートメントを READ COMMITTED および REPEATABLE READ 分離レベルで処理します。読み取り一貫性では、アクセスするテーブルに一切ロックが設定されません。このため、読み取り一貫性がテーブルで実行されているときにも、他のユーザはこれらのテーブルを自由に変更できます。


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

7.5.9.3 ロックを取得する読み取り SELECT ... FOR UPDATE および SELECT ... LOCK IN SHARE MODE

読み取り一貫性は、状況によっては不便な場合があります。 テーブル CHILD に新しいレコードを追加するために、テーブル PARENT 内にこの子レコードの親がすでに存在することを確認するとします。

仮に、読み取り一貫性でテーブル PARENT を読み取り、このテーブルで子レコードの親の存在を確認したとします。これでテーブル CHILD に子レコードを確実に追加できるでしょうか。できません。この処理の間に他のユーザがテーブル PARENT から親レコードを削除しても気付かないからです。

これに対処するには、共有ロックモード LOCK IN SHARE MODESELECT 文を実行します。
 
SELECT * FROM PARENT WHERE NAME = 'Jones' LOCK IN SHARE MODE;

共有モードで読み取りを実行すると、入手可能な最新のデータが読み取られ、読み取ったレコードに共有モードロックが設定されます。 その最新データが、別のユーザのまだコミットされていないトランザクションに属している場合は、そのトランザクションがコミットされるまで待機します。 共有モードロックによって、読み取ったレコードは他のユーザから更新または削除されなくなります。上記のクエリから親である 'Jones' が返されたことを確認したうえで、テーブル CHILD'Jones' の子レコードを確実に追加し、トランザクションをコミットできます。 この例は、アプリケーションコードで参照整合性を実装する方法を示しています。

別の例を見てみましょう。テーブル CHILD_CODES に整数のカウンタフィールドがあります。このテーブルは、テーブル CHILD に追加する各子に一意の識別子を割り当てるために使用します。 このカウンタの現在の値を読み取る場合に、読み取り一貫性または共有モード読み取りが適していないのは明らかです。これは、データベースの 2 人のユーザに同じカウンタ値が返されるために、テーブルに同じ識別子を持つ 2 つの子を追加することになり、重複キーエラーが発生するためです。

この場合、カウンタの読み取りとインクリメントを実装する方法が 2 つあります。(1)カウンタを先に 1 増加してから読み取る方法と(2)カウンタを先にロックモード FOR UPDATE で読み取ってからインクリメントする方法です。

 
SELECT COUNTER_FIELD FROM CHILD_CODES FOR UPDATE;
UPDATE CHILD_CODES SET COUNTER_FIELD = COUNTER_FIELD + 1;

SELECT ... FOR UPDATE では、入手可能な最新のデータが読み取られ、読み取った各レコードに排他ロックが設定されます。 したがって、検索された SQL UPDATE がレコードに設定するロックと同じロックが設定されます。


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

7.5.9.4 ネクストキーロック: ファントムの問題の回避

InnoDB は、行レベルのロックでネクストキーロックと呼ばれるアルゴリズムを使用します。 InnoDB が行レベルロックを行うのは、テーブルのインデックスを検索またはスキャンする際に、検出したインデックスレコードに共有ロックまたは排他ロックを設定するためです。このため、行レベルロックは正確にはインデックスレコードロックと呼ばれます。

InnoDB がインデックスレコードに設定するロックは、そのインデックスレコードの前の 'ギャップ' にも影響します。あるユーザがインデックスのレコード R に共有ロックまたは排他ロックを設定すると、他のユーザはインデックス順で R の直前に新しいインデックスレコードを挿入できなくなります。 このようなギャップのロックには、いわゆるファントムの問題を回避する目的があります。たとえば、テーブル CHILD から 100 より大きい ID を持つすべてのレコードを読み取ってロックし、選択したレコードに対してフィールドを更新するとします。

 
SELECT * FROM CHILD WHERE ID > 100 FOR UPDATE;

テーブル CHILD のカラム ID にインデックスがあるとします。クエリでは、ID が 100 より大きい最初のレコードから順にそのインデックスがスキャンされます。 ここで、インデックスレコードに設定されたロックがギャップで行われる挿入をロックアウトしないと、テーブルに新しいレコードが挿入される可能性があります。その場合に、トランザクションで次のステートメントをもう一度実行してみます。

 
SELECT * FROM CHILD WHERE ID > 100 FOR UPDATE;

すると、クエリから返される結果セットに新しいレコードが含まれることになります。 これは、トランザクションの分離の原則に反します。 つまり、トランザクションの実行中は、読み取ったデータが変化しないことが必要です。一組のレコードを 1 つのデータ項目と見なすと、新たな 'ファントムの' レコードによって、この分離の原則が破られることになります。

InnoDB では、インデックスをスキャンする際に、インデックス内の最後のレコードの後のギャップもロックできます。前の例と同様に、InnoDB が設定したロックによって、テーブル内の ID が 100 より大きい箇所への挿入が防止されます。

ネクストキーロックを使用して、アプリケーションに一意性のチェックを実装できます。共有モードでデータを読み取り、挿入しようとするレコードに重複が見られなければ、レコードを確実に挿入できます。また、読み取り中は対象となるレコードの後続のレコードにネクストキーロックが設定されて、第三者による重複レコードの挿入を防ぎます。このように、ネクストキーロックによって、テーブル内に存在しないものを 'ロック' することができます。


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

7.5.9.5 InnoDB で各種 SQL ステートメントによって設定されるロック


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

7.5.9.6 デッドロックの検出とロールバック

InnoDB は、トランザクションのデッドロックを自動的に検出し、そのトランザクションをロールバックしてデッドロックを回避します。バージョン 4.0.5 より、InnoDB は小さいほうのトランザクションを選択してロールバックするようになります。トランザクションのサイズは、挿入、更新、または削除したレコードの数によって決定されます。 4.0.5 より前のバージョンの InnoDB では、デッドロックを引き起こすロックを要求したトランザクションを、常にロールバックしていました。

InnoDB は、MySQL の LOCK TABLES ステートメントが設定したロックが関係するデッドロック、または InnoDB 以外のストレージエンジンで設定されたロックが関係するデッドロックを検出できません。これらの状況は、`my.cnf' で設定する innodb_lock_wait_timeout を使って解決する必要があります。

InnoDB がトランザクションの完全なロールバックを実行すると、そのトランザクションのすべてのロックが解除されます。ところが、エラーのために単一の SQL ステートメントのみがロールバックされると、SQL が設定したロックの一部が保持される場合があります。これは、InnoDB が使用する行ロックの格納形式では、ロックを設定した SQL ステートメントを後から特定できないためです。


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

7.5.9.7 InnoDB での読み取り一貫性の例

デフォルトの REPEATABLE READ 分離レベルで実行しているとします。 一貫した読み取り(このレベルでは、通常の SELECT ステートメントは読み取り一貫性がある) では、クエリがデータベースを参照するときの基準となるタイムポイントを、InnoDB はトランザクションに割り当てます。こうして、タイムポイントが割り当てられた後に(セッションごとのスナップショットを取った後に)、他のトランザクションがレコードを削除してコミットしたとしても、一度読み取った内容は変わりません(トランザクション中の読み取り内容は同じです)。挿入と更新も同様です。

割り当てられたタイムポイントを先に進めるには、トランザクションをコミットし、新たな SELECT を実行します。

これは、マルチバージョン並行処理制御(multi-versioned concurrency control)と呼ばれます。

 
                  ユーザ A               ユーザ B

              SET AUTOCOMMIT=0;      SET AUTOCOMMIT=0;
時間経過
|             SELECT * FROM t;
|             empty set
|                                    INSERT INTO t VALUES (1, 2);
|
v             SELECT * FROM t;
              empty set
                                     COMMIT;

              SELECT * FROM t;
              empty set;

              COMMIT;

              SELECT * FROM t;
              ---------------------
              |    1    |    2    |
              ---------------------

このように、ユーザ B が挿入したレコードをユーザ A が参照できるのは、B が挿入をコミットした後で、A がコミットした後になります。また、A が自分のトランザクションをコミットしたことで、時点が B のコミットより先に進みます。

データベースの "最新の" 状態を参照するには、共有ロックを利用した読み取りを使用する必要があります。

 
SELECT * FROM t LOCK IN SHARE MODE;


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

7.5.9.8 デッドロックの対処法

デッドロックはトランザクションデータベースにおける従来からの問題ですが、一部のトランザクションを実行できなくなるほど頻繁に発生するのでなければ危険ではありません。通常は、アプリケーションを作成する際に、デッドロックのためにロールバックされたトランザクションを再発行できるようにしておく必要があります。

InnoDB は、自動で行レベルロックを使用します。単一のレコードを挿入または削除するだけのトランザクションでもデッドロックが発生します。それは、これらの操作が実際には原子性を持つものではなく、挿入/削除するレコードのインデックスレコード(おそらくは複数)に自動的にロックを設定するためです。

デッドロックに対処し、デッドロックの発生頻度を減らすための方法を次に示します。


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

7.5.10 パフォーマンスチューニングのヒント

  1. Unix の `top' または Windows の`タスクマネージャ'で表示されたプロセスの CPU 使用率が 70% 未満である場合、おそらくそのプロセスはディスク処理である。トランザクションコミットの数が多すぎるか、バッファプールが小さすぎることが考えられる。 バッファプールは大きくした方がよいが、物理メモリの 80% を超えないようにする。

  2. 複数の変更処理を 1 つのトランザクションにまとめる。InnoDB は、データベースを変更するトランザクションがコミットされるたびにログをディスクにフラッシュする必要がある。一般にディスクの回転速度は最高でも 1 秒間に 167 回転(10000rpmの規格の物の場合)であるため、ディスクがオペレーティングシステムを欺かない限り、コミットの回数も同じく 1 秒間に 167 回に制限される。

  3. 最近コミットされたトランザクションの一部を失ってもかまわない場合は、`my.cnf' のパラメータ innodb_flush_log_at_trx_commit を 0 に設定できる。InnoDB は、いずれにしても 1 秒間に 1 回ログをフラッシュしようとする。ただし、このフラッシュは保証されない。

  4. ログファイルをバッファプールと同じぐらい大きくする。InnoDB は、ログファイルの最後まで書き込むと、チェックポイントでバッファプールの変更された内容をディスクに書き込まなければならない。ログファイルが小さいと、不必要に何度もディスクへ書き込むことになる。大きなログファイルの難点は、リカバリに時間がかかることである。

  5. ログバッファも大きくする必要がある(8 MB など)。

  6. (3.23.39 以降に関係) Linux および Unix の一部のバージョンでは、Unix の fdatasync やその他の類似する方法を使ってファイルをディスクにフラッシュする際に、かなりの時間がかかる。 InnoDB は、デフォルトで fdatasync 関数を使用する。 データベースへ書き込む際のパフォーマンスが不満であれば、`my.cnf' の innodb_flush_methodO_DSYNC に設定してもかまわない。ただし、ほとんどのシステムでは O_DSYNC の方が処理が遅くなると思われる。

  7. InnoDB にデータをインポートするときは、autocommit がオン(1)になっていないことを確認する。その場合、挿入のたびにディスクへのログのフラッシュが要求される。 SQL の単純なファイルインポート行の前に次の行を追加する。

     
    SET AUTOCOMMIT=0;
    

    さらにその後に次の行を追加する。

     
    COMMIT;
    

    `mysqldump' のオプション --opt を使用すると、上記のように SET AUTOCOMMIT=0; ... COMMIT; ラッパで囲まなくても、ダンプファイルを取得して InnoDB テーブルに高速でインポートできる。

  8. 大量に INSERT する時の大規模なロールバックに注意する。InnoDB は、挿入バッファを使って挿入時のディスク I/O を削減するが、対応するロールバックではそのようなメカニズムが使用されない。ディスクバウンドのロールバックには、対応する挿入の 30 倍の時間がかかる。データベースのプロセスを強制終了しても、データベース起動時に再度ロールバックが開始されるので役に立たない。ロールバックの暴走を回避するには、ロールバックが CPU とメモリだけで高速に実行されるようにバッファプールを拡大するか、InnoDB データベース全体を削除するしかない。

  9. 他の大規模なディスクバウンドの操作にも注意する。 DROP TABLE または TRUNCATE(MySQL-4.0 以降)を使用してテーブルを空にする。DELETE FROM yourtable は使用しない。

  10. 多数のレコードを挿入する場合は、複数行の INSERT を使用して、サーバとクライアント間の通信にかかるオーバヘッドを軽減する。

     
    INSERT INTO yourtable VALUES (1, 2), (5, 5);
    

    この方法は、InnoDB だけでなく他のテーブル型へ挿入する場合にも有効である。

7.5.10.1 SHOW INNODB STATUSInnoDB モニタ   


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

7.5.10.1 SHOW INNODB STATUSInnoDB モニタ

バージョン 3.23.42 より、InnoDB の内部状態に関する情報を出力する InnoDB モニタが InnoDB に組み込まれました。 バージョン 3.23.52 および 4.0.3 より、SQL コマンド SHOW INNODB STATUS を使用して、標準 InnoDB モニタの出力を SQL クライアントへ取り込めるようになりました。 このデータは、パフォーマンスチューニングに役立ちます。`mysql' 対話型 SQL クライアントを使用している場合は、ステートメントの末尾にあるセミコロンを \G に置き換えることで、出力が判読しやすくなります。
 
SHOW INNODB STATUS\G

InnoDB モニタのもう 1 つの使い方として、サーバ `mysqld' の標準出力に InnoDB モニタから継続的にデータを書き込むことができます(注意: MySQL クライアントからは何も出力されません)。 この機能をオンにすると、InnoDB モニタは約 15 秒ごとにデータを出力するようになります。`mysqld' をデーモンとして実行すると、通常はこの出力が MySQL datadir 内の `.err' ログに出力されます。 このデータは、パフォーマンスチューニングに役立ちます。 Windows でこの出力を MS-DOS コマンドプロンプトにリダイレクトするには、MS-DOS コマンドプロンプトから --console オプションを指定して mysqld-max を実行する必要があります。

別途用意されている innodb_lock_monitor では、innodb_monitor と同じ情報に加えて、各トランザクションが設定したロックに関する情報も出力されます。

出力される情報には、以下に関するデータが含まれます。

InnoDB モニタは、次の SQL コマンドで起動できます。

 
CREATE TABLE innodb_monitor (a INT) TYPE = innodb;

また、次のコマンドで停止できます。

 
DROP TABLE innodb_monitor;

CREATE TABLE 構文は、MySQL SQL パーサを通して InnoDB エンジンにコマンドを渡す手段に過ぎません。作成されたテーブルは InnoDB モニタとまったく無関係です。モニタの実行中にデータベースをシャットダウンし、その後で再びモニタを起動する場合は、まず作成したテーブルを破棄しないと、新たな CREATE TABLE 発行してモニタを起動することができません。 この構文は、将来のリリースで変更される可能性があります。

次に示すのは、InnoDB モニタの出力サンプルです。

 
================================
010809 18:45:06 INNODB MONITOR OUTPUT
================================
--------------------------
LOCKS HELD BY TRANSACTIONS
--------------------------
LOCK INFO:
Number of locks in the record hash table 1294
LOCKS FOR TRANSACTION ID 0 579342744
TABLE LOCK table test/mytable trx id 0 582333343 lock_mode IX

RECORD LOCKS space id 0 page no 12758 n bits 104 table test/mytable index
PRIMARY trx id 0 582333343 lock_mode X
Record lock, heap no 2 PHYSICAL RECORD: n_fields 74; 1-byte offs FALSE;
info bits 0
 0: len 4; hex 0001a801; asc ;; 1: len 6; hex 000022b5b39f; asc ";;
 2: len 7; hex 000002001e03ec; asc ;; 3: len 4; hex 00000001;
...
-----------------------------------------------
CURRENT SEMAPHORES RESERVED AND SEMAPHORE WAITS
-----------------------------------------------
SYNC INFO:
Sorry, cannot give mutex list info in non-debug version!
Sorry, cannot give rw-lock list info in non-debug version!
-----------------------------------------------------
SYNC ARRAY INFO: reservation count 6041054, signal count 2913432
4a239430 waited for by thread 49627477 op. S-LOCK file NOT KNOWN line 0
Mut ex 0 sp 5530989 r 62038708 sys 2155035;
rws 0 8257574 8025336; rwx 0 1121090 1848344
-----------------------------------------------------
CURRENT PENDING FILE I/O'S
--------------------------
Pending normal aio reads:
Reserved slot, messages 40157658 4a4a40b8
Reserved slot, messages 40157658 4a477e28
...
Reserved slot, messages 40157658 4a4424a8
Reserved slot, messages 40157658 4a39ea38
Total of 36 reserved aio slots
Pending aio writes:
Total of 0 reserved aio slots
Pending insert buffer aio reads:
Total of 0 reserved aio slots
Pending log writes or reads:
Reserved slot, messages 40158c98 40157f98
Total of 1 reserved aio slots
Pending synchronous reads or writes:
Total of 0 reserved aio slots
-----------
BUFFER POOL
-----------
LRU list length 8034
Free list length 0
Flush list length 999
Buffer pool size in pages 8192
Pending reads 39
Pending writes: LRU 0, flush list 0, single page 0
Pages read 31383918, created 51310, written 2985115
----------------------------
END OF INNODB MONITOR OUTPUT
============================
010809 18:45:22 InnoDB starts purge
010809 18:45:22 InnoDB purged 0 pages

この出力についていくつかの注釈があります。


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

7.5.11 マルチバージョニングの実装

InnoDB はマルチバージョニングのデータベースであるため、テーブルスペース内の古いバージョンのレコードに関する情報を保持しなければなりません。この情報は、ロールバックセグメントに格納されます。 ロールバックセグメントは Oracle のロールバックセグメントのデータ構造に似ています。

InnoDB は内部的に、データベースに格納されている各レコードに 2 つのフィールドを付加します。 6 バイトのフィールドには、レコードを最後に挿入または更新したトランザクションの識別子が記録されます(トランザクション ID)。 削除も内部的には更新として扱われ、レコード内の特別なビットに削除済みとしてマークされます。 各レコードには、ロールポインタと呼ばれる 7 バイトのフィールドも付加されます。ロールポインタは、ロールバックセグメントに書き込まれた UNDO ログレコードを指します。レコードが更新された場合は、更新前のレコードの内容を再構築するために必要な情報が UNDO ログレコードに記録されます。

InnoDB は、ロールバックセグメント内の情報を使用して、トランザクションのロールバックで必要な取り消し操作を実行します。また、読み取り一貫性のために、以前のバージョンのレコードを構築する場合にも、この情報が使用されます。

ロールバックセグメント内の UNDO ログは、挿入用の UNDO ログと更新用の UNDO ログに分かれています。挿入用の UNDO ログは、トランザクションロールバックにのみ必要で、トランザクションがコミットされると直ちに破棄されます。更新用の UNDO ログは、読み取り一貫性でも使用されるため、InnoDB がスナップショットを割り当てたトランザクションが存在しなくなるまで破棄できません。このようなトランザクションでは、読み取り一貫性で以前のバージョンのレコードを構築するために、更新用の UNDO ログの情報が必要となる場合があるからです。

トランザクションは定期的にコミットする必要があります。読み取り一貫性のある物のみを発行するトランザクションも同様です。 そうしないと、InnoDB が更新用 UNDO ログからデータを破棄できなくなり、ロールバックセグメントが大きくなって、テーブルスペースがフルになるおそれがあります。

ロールバックセグメントにおける UNDO ログレコードの物理サイズは、通常、対応する挿入レコードまたは更新レコードよりも小さくなります。ロールバックセグメントに必要な領域を、これらのレコード長を使って、計算できます。

このマルチバージョニングの基本構想では、SQL ステートメントでレコードを削除しても、すぐにはそのレコードがデータベースから物理的に削除されません。 削除に対して書き込まれた更新取り消しログレコードを InnoDB が破棄できるようになった時点で、対応するレコードとそのインデックスレコードがデータベースから物理的に削除されます。この削除操作はパージと呼ばれます。この操作はきわめて高速で、通常は削除を行った SQL ステートメントと同程度の時間しかかかりません。


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

7.5.12 テーブルとインデックスの構造

MySQL は、テーブルのデータディクショナリ情報を、データベースディレクトリ内の `.frm' ファイルに保存します。ところが、InnoDB 型のテーブルは、テーブルスペース内の InnoDB 内部データディクショナリにも独自のエントリを持っています。MySQL は、テーブルやデータベースを破棄するときに、`.frm' ファイルおよび InnoDB データディクショナリ内の対応するエントリの両方を削除する必要があります。 このために、単に `.frm' ファイルを移動するだけではデータベース間で InnoDB テーブルを移動できません。また、MySQL 3.23.43 以下のバージョンで InnoDB 型のテーブルがあると DROP DATABASE が機能しなかったのもこれが原因です。

すべての InnoDB テーブルには、クラスタードインデックスと呼ばれる、レコードのデータを格納する特別なインデックスがあります。テーブルで PRIMARY KEY を定義すると、主キーのインデックスがクラスタードインデックスになります。

テーブルに主キーを定義しない場合は、InnoDB によって内部的にクラスタードインデックスが作成され、そこで InnoDB がテーブル内のレコードに割り当てるロー ID の順にレコードが並べられます。ロー ID は 6 バイトのフィールドで、新しいレコードが挿入されると単純に数が増加していきます。したがって、ロー ID の順に並べられたレコードは、物理的に挿入された順で並ぶことになります。

クラスタードインデックスを介したレコードへのアクセスは迅速です。これは、インデックス検索が行われるページにレコードデータが配置されるためです。他の多くのデータベースでは、データがインデックスレコードとは別のページに伝統的に格納されています。一般に、テーブルが大きい場合は、クラスタードインデックスの方が従来の方法よりもディスク I/O が少なくなります。

InnoDB では、非クラスタードインデックス(セカンダリインデックスとも呼ばれる)のレコードにレコードの主キー値が含まれています。InnoDB はこの主キー値を使用して、クラスタードインデックスからレコードを検索します。主キーが長いと、セカンダリインデックスの使用する領域が増えることに注意してください。

7.5.12.1 インデックスの物理構造   
7.5.12.2 挿入バッファ   
7.5.12.3 ハッシュインデックス   
7.5.12.4 物理的なレコード構造   
7.5.12.5 InnoDB での AUTO_INCREMENT カラムの仕組み   


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

7.5.12.1 インデックスの物理構造

InnoDB のすべてのインデックスは B ツリーで、インデックスのレコードはツリーのリーフページに格納されます。インデックスページのデフォルトサイズは 16 KB です。新しいレコードが挿入されると、InnoDB はページの 1/16 を、将来のインデックスレコードの挿入や更新に備えて空けようとします。

インデックスレコードがシーケンシャル(昇順または降順)に挿入されると、インデックスページの約 15/16 までがいっぱいになります。 レコードがランダムに挿入された場合は、ページの 1/2 〜 15/16 までがいっぱいになります。インデックスページの使用容量が 1/2 未満になると、InnoDB はインデックスツリーを縮小してページを解放しようとします。


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

7.5.12.2 挿入バッファ

データベースアプリケーションでは、主キーが一意の識別子であり、新しいレコードが主キーの昇順で挿入されることが一般的です。したがって、クラスタードインデックスへの挿入では、ディスクからのランダムな読み取りを必要としません。

一方、セカンダリインデックスは通常一意ではなく、セカンダリインデックスへの挿入は比較的ランダムに行われます。 このため、InnoDB で特別なメカニズムが使用されることなく、多数のランダムなディスク I/O が発生します。

一意でないセカンダリインデックスにインデックスレコードが挿入される場合は、セカンダリインデックスページがすでにバッファプール内にあるかどうかが InnoDB によってチェックされます。すでにある場合は、InnoDB によってインデックスページに直接レコードが挿入されます。バッファプール内にインデックスページがなかった場合は、InnoDB によって特別な挿入バッファ構造にレコードが挿入されます。 挿入バッファは、その全体がバッファプール内に収まるように小さくしてあるため、このバッファへの挿入はきわめて高速です。

挿入バッファは、データベース内のセカンダリインデックスツリーに定期的にマージされます。インデックスツリーの同じページ上で複数の挿入をマージすることで、ディスク I/O を削減できます。 挿入バッファによってテーブルへの挿入速度が最大 15 倍に高められることが測定されています。


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

7.5.12.3 ハッシュインデックス

データベースのほぼ全体がメインメモリ内に収まる場合に、そのデータベースで最も速くクエリを実行するには、ハッシュインデックスを使用します。InnoDB には、テーブルに定義されたインデックスで実行される検索を監視するメカニズムがあり、ハッシュインデックスの構築がクエリにとって有益であると InnoDB が判断した場合は、自動的にそのインデックスが構築されます。

ただし、ハッシュインデックスは常にテーブルに存在する B ツリーインデックスを基に構築されるので注意が必要です。 InnoDB は、B ツリーインデックス上で検出した検索パターンに応じて、任意の長さのキー(B ツリーに定義されたキー)の先頭部分に、ハッシュインデックスを構築できます。 ハッシュインデックスは部分的であってもかまいません。つまり、B ツリーインデックス全体をバッファプールにキャッシュする必要はありません。InnoDB は、頻繁にアクセスされるインデックスページへの要求に応じてハッシュインデックスを構築します。

ある意味では、柔軟なハッシュインデックスのメカニズムを使用して、InnoDB が十分に余裕のあるメインメモリに適応することで、メインメモリデータベースのアーキテクチャに近づいています。


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

7.5.12.4 物理的なレコード構造


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

7.5.12.5 InnoDB での AUTO_INCREMENT カラムの仕組み

データベース起動後に、オートインクリメントカラムが定義されたテーブル T にユーザが最初に挿入を行う際にそのカラムに明示的に値を指定しなかった場合は、InnoDB によって SELECT MAX(auto-inc-column) FROM T が実行され、その結果の値に 1 を加えた値が、このカラムおよびテーブルのオートインクリメントカウンタに割り当てられます。 これを、「テーブル T のオートインクリメントカウンタが初期化された」と表現します。

InnoDB は、新たに作成されたテーブルに対するオートインクリメントカウンタの初期化で、これと同じ手順を実行します。

ユーザが挿入時にオートインクリメントカラムに値 0 を指定すると、InnoDB は値が指定されなかったものとしてレコードを扱うことに注意してください。

オートインクリメントカウンタが初期化された後に、ユーザがオートインクリメントカラムの値を明示的に指定してレコードを挿入した時、その値が現在のカウンタ値より大きい場合は、カウンタは指定された値に設定されます。ユーザが値を明示的に指定しなかった場合は、InnoDB によってカウンタが 1 つ増加され、その新しい値がカラムに割り当てられます。

カウンタから値が割り当てられるときは、オートインクリメントのメカニズムによって、ロックとトランザクションの処理が省略されます。このため、カウンタから数値を取得したトランザクションをロールバックすると、数値の順序にずれが生じることもあります。

ユーザがオートインクリメントカラムに負の値を指定した場合、または、整数型に格納できる最大の整数値より大きな値を指定した場合の、オートインクリメントの動作は定義されていません。


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

7.5.13 ファイル領域の管理とディスク I/O

7.5.13.1 ディスク I/O   
7.5.13.2 ファイル領域管理   
7.5.13.3 InnoDB テーブルのデフラグメント化   


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

7.5.13.1 ディスク I/O

InnoDB は、ディスク I/O で非同期 I/O を使用します。Windows NT では、オペレーティングシステムが提供するネイティブの非同期 I/O が使用されます。 Unix では、InnoDB に組み込まれた疑似的な非同期 I/O が使用されます。InnoDB は、多数の I/O スレッドを作成して、先読みなどの I/O 操作に対応します。将来のバージョンでは、Windows NT の疑似 aio、および Unix のネイティブ aio(装備されている場合)が追加でサポートされるようになります。

Windows NT では、InnoDB はバッファなしの I/O を使用します。つまり、InnoDB が読み書きするディスクページが、オペレーティングシステムのファイルキャッシュにバッファされません。これによって、メモリの使用帯域幅をある程度節約できます。

3.23.41 より、InnoDB は二重書き込みと呼ばれる斬新なファイルフラッシュ技法を使用するようになりました。 この技法によって、オペレーティングシステムのクラッシュや停電後のリカバリがより安全になります。また、fsync 操作の必要性を軽減することで、ほとんどの Unix フレーバでパフォーマンスが向上します。

二重書き込みでは、InnoDB がデータファイルにページを書き込む前に、まず二重書き込みバッファと呼ばれる隣接するテーブルスペースに、それらのページが書き込まれます。書き込みおよび二重書き込みバッファへのフラッシュが完了した後で初めて、InnoDB はデータファイルの適切な場所にページを書き込みます。このページへの書き込みの最中にオペレーティングシステムがクラッシュした場合は、InnoDB が二重書き込みバッファから適切なページのコピーを探し出してリカバリを行います。

3.23.41 よりローデバイスもデータファイルとして使用できるようになりましたが、このテストはまだ完了していません。新しいデータファイルを作成するときに、innodb_data_file_path で指定したデータファイルサイズの直後に newraw キーワードを付加する必要があります。パーティションは、少なくとも指定したサイズと同じ大きさでなければなりません。 InnoDB での 1M は 1,024 x 1,024 バイトですが、通常のディスクの仕様では、1 MB は 1,000,000 バイトを意味することに注意してください。

 
innodb_data_file_path=/dev/hdd1:5Gnewraw;/dev/hdd2:2Gnewraw

サーバを再起動する前に、キーワードを raw に変更する必要があります。そうしないと InnoDB がパーティションを上書きします。

 
innodb_data_file_path=/dev/hdd1:5Graw;/dev/hdd2:2Graw

Unix の一部のバージョンでは、ローデバイスを使用することで、バッファなしの I/O を実行できます。

ローデバイスを使用するときは、MySQL サーバを実行する OS のアカウントに、それらのパーティション(上記例では/dev/hdd1)に対して読み書きできる権限があることを確認してください。

InnoDB には、先読み方法として、シーケンシャルな先読みとランダムな先読みの 2 種類があります。シーケンシャルな先読みでは、テーブルスペース内のセグメントへのアクセスパターンがシーケンシャルであることを InnoDB が検知します。 この場合 InnoDB は、一連のデータベースページの読み取りを事前に 1 つにまとめて I/O システムに送信します。ランダムな先読みでは、テーブルスペース内のある領域がバッファプールへ完全に読み取られている最中であることを InnoDB が検知します。この場合、InnoDB は残りの読み取りを I/O システムに送信します。


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

7.5.13.2 ファイル領域管理

オプション設定ファイルに定義するデータファイルから、InnoDB のテーブルスペースが構成されます。これらのファイルは、単純に連結されてテーブルスペースになります。ストライピングは使用されません。 現時点では、テーブルスペースのどの位置にテーブルが割り当てられるかを定義できません。ただし、新たに作成されるテーブルスペースでは、InnoDB が末端からスペースを割り当てます。

テーブルスペースは、デフォルトサイズが 16 KB のデータベースページで構成されます。 これらのページは、64個の連続するページから成るエクステントにグループ化されます。InnoDB では、テーブルスペース内部の 'ファイル' をセグメントと呼びます。ロールバックセグメントという名前は、多少誤解を招くおそれがあります。これは、ロールバックセグメントが実際にはテーブルスペース内の多数のセグメントを含んでいるためです。

InnoDB では、各インデックスに 2 つのセグメントが割り当てられます。1 つは B ツリーの非リーフノード用、もう 1 つはリーフノード用です。これには、データを含んでいるリーフノードで連続性を高める意図があります。

テーブルスペース内でセグメントが大きくなると、InnoDB はそのセグメントに最初の 32 ページを個別に割り当てます。その後は、エクステント全体がセグメントに割り当てられます。 InnoDB では、データの連続性を確保するために、大きなセグメントに一度に最大 4 つのエクステントを追加できます。

テーブルスペースには、他のページのビットマップを含んだページがあるため、InnoDB テーブルスペース内のいくつかのエクステントは、全体としてではなく個別のページとしてのみセグメントに割り当てることができます。

クエリ SHOW TABLE STATUS FROM ... LIKE ... を発行してテーブルスペース内の空き領域を照会すると、InnoDB からテーブルスペース内の完全に空いているエクステントが報告されます。 InnoDB は、常にいくつかのエクステントをクリーンアップとその他の内部的な用途のために確保しています。これらのエクステントは空き領域に含まれません。

テーブルからデータを削除すると、InnoDB によって対応する B ツリーインデックスが縮小されます。これによって個々のページまたはエクステントがテーブルスペースに解放されて、他のユーザがその領域を利用できるようになるかどうかは、削除のパターンによって異なります。テーブルを破棄するか、またはテーブルからすべてのレコードを削除すると、他のユーザに確実に領域が解放されます。ただし、削除されたレコードは、トランザクションロールバックまたは一貫した読み取りでそのレコードが必要なくなった後のパージ操作で初めて物理的に削除されることに留意してください。


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

7.5.13.3 InnoDB テーブルのデフラグメント化

InnoDB テーブルのインデックスでランダムな挿入または削除が行われると、インデックスがフラグメント化されることがあります。 フラグメント化とは、ディスクでのインデックスページの物理的な順序が、ページでのレコードのアルファベット順とかけ離れていること、またはインデックスに割り当てられた 64 ページのブロック内に多数の未使用ページがあることを意味します。

インデックスのスキャンを速くするには、定期的に mysqldump を使ってテーブルをテキストファイルにダンプしてからテーブルを破棄し、ダンプからテーブルを再ロードします。 デフラグメント化のもう 1 つの方法として、テーブル変更操作 ALTER TABLE tablename TYPE=InnoDB を実行します。 これによって、MySQL がテーブルを再構築します。

インデックスへの挿入が常に昇順で行われ、レコードが必ず末尾から削除される場合は、InnoDB のファイル領域管理アルゴリズムによってインデックスのフラグメント化が発生しないことが保証されます。


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

7.5.14 エラー処理

InnoDB でのエラー処理は、必ずしも SQL 標準に明記されているとおりではありません。SQL-99 では、SQL ステートメントでエラーが発生した場合は、そのステートメントでロールバックを実行するように記述されています。InnoDB では、ステートメントの一部のみ、またはトランザクション全体がロールバックされることがあります。 次のリストは、InnoDB でのエラー処理の仕様です。


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

7.5.15 InnoDB テーブルの制限事項


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

7.5.16 InnoDB の変更履歴

7.5.16.1 MySQL/InnoDB-4.1.1(2003 年 12 月 4 日)   
7.5.16.2 MySQL/InnoDB-4.0.16(2003 年 10 月 22 日)   
7.5.16.3 MySQL/InnoDB-3.23.58(2003 年 9 月 15 日)   
7.5.16.4 MySQL/InnoDB-4.0.15(2003 年 9 月 10 日)   
7.5.16.5 MySQL/InnoDB-4.0.14(2003 年 7 月 22 日)   
7.5.16.6 MySQL/InnoDB-3.23.57(2003 年 6 月 20 日)   
7.5.16.7 MySQL/InnoDB-4.0.13(2003 年 5 月 20 日)   
7.5.16.8 MySQL/InnoDB-4.1.0(2003 年 4 月 3 日)   
7.5.16.9 MySQL/InnoDB-3.23.56(2003 年 3 月 17 日)   
7.5.16.10 MySQL/InnoDB-4.0.12(2003 年 3 月 18 日)   
7.5.16.11 MySQL/InnoDB-4.0.11(2003 年 2 月 25 日)   
7.5.16.12 MySQL/InnoDB-4.0.10(2003 年 2 月 4 日)   
7.5.16.13 MySQL/InnoDB-3.23.55(2003 年 1 月 24 日)   
7.5.16.14 MySQL/InnoDB-4.0.9(2003 年 1 月 14 日)   
7.5.16.15 MySQL/InnoDB-4.0.8(2003 年 1 月 7 日)   
7.5.16.16 MySQL/InnoDB-4.0.7(2002 年 12 月 26 日)   
7.5.16.17 MySQL/InnoDB-4.0.6(2002 年 12 月 19 日)   
7.5.16.18 MySQL/InnoDB-3.23.54(2002 年 12 月 12 日)   
7.5.16.19 MySQL/InnoDB-4.0.5(2002 年 11 月 18 日)   
7.5.16.20 MySQL/InnoDB-3.23.53(2002 年 10 月 9 日)   
7.5.16.21 MySQL/InnoDB-4.0.4(2002 年 10 月 2 日)   
7.5.16.22 MySQL/InnoDB-4.0.3(2002 年 8 月 28 日)   
7.5.16.23 MySQL/InnoDB-3.23.52(2002 年 8 月 16 日)   
7.5.16.24 MySQL/InnoDB-4.0.2(2002 年 7 月 10 日)   
7.5.16.25 MySQL/InnoDB-3.23.51(2002 年 6 月 12 日)   
7.5.16.26 MySQL/InnoDB-3.23.50(2002 年 4 月 23 日)   
7.5.16.27 MySQL/InnoDB-3.23.49(2002 年 2 月 17 日)   
7.5.16.28 MySQL/InnoDB-3.23.48(2002 年 2 月 9 日)   
7.5.16.29 MySQL/InnoDB-3.23.47(2001 年 12 月 28 日)   
7.5.16.30 MySQL/InnoDB-4.0.1(2001 年 12 月 23 日)   
7.5.16.31 MySQL/InnoDB-3.23.46(2001 年 11 月 30 日)   
7.5.16.32 MySQL/InnoDB-3.23.45(2001 年 11 月 23 日)   
7.5.16.33 MySQL/InnoDB-3.23.44(2001 年 11 月 2 日)   
7.5.16.34 MySQL/InnoDB-3.23.43(2001 年 10 月 4 日)   
7.5.16.35 MySQL/InnoDB-3.23.42(2001 年 9 月 9 日)   
7.5.16.36 MySQL/InnoDB-3.23.41(2001 年 8 月 13 日)   
7.5.16.37 MySQL/InnoDB-3.23.40(2001 年 7 月 16 日)   
7.5.16.38 MySQL/InnoDB-3.23.39(2001 年 6 月 13 日)   
7.5.16.39 MySQL/InnoDB-3.23.38(2001 年 5 月 12 日)   


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

7.5.16.1 MySQL/InnoDB-4.1.1(2003 年 12 月 4 日)


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

7.5.16.2 MySQL/InnoDB-4.0.16(2003 年 10 月 22 日)


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

7.5.16.3 MySQL/InnoDB-3.23.58(2003 年 9 月 15 日)


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

7.5.16.4 MySQL/InnoDB-4.0.15(2003 年 9 月 10 日)


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

7.5.16.5 MySQL/InnoDB-4.0.14(2003 年 7 月 22 日)


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

7.5.16.6 MySQL/InnoDB-3.23.57(2003 年 6 月 20 日)


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

7.5.16.7 MySQL/InnoDB-4.0.13(2003 年 5 月 20 日)


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

7.5.16.8 MySQL/InnoDB-4.1.0(2003 年 4 月 3 日)


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

7.5.16.9 MySQL/InnoDB-3.23.56(2003 年 3 月 17 日)


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

7.5.16.10 MySQL/InnoDB-4.0.12(2003 年 3 月 18 日)


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

7.5.16.11 MySQL/InnoDB-4.0.11(2003 年 2 月 25 日)


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

7.5.16.12 MySQL/InnoDB-4.0.10(2003 年 2 月 4 日)


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

7.5.16.13 MySQL/InnoDB-3.23.55(2003 年 1 月 24 日)


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

7.5.16.14 MySQL/InnoDB-4.0.9(2003 年 1 月 14 日)


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

7.5.16.15 MySQL/InnoDB-4.0.8(2003 年 1 月 7 日)


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

7.5.16.16 MySQL/InnoDB-4.0.7(2002 年 12 月 26 日)


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

7.5.16.17 MySQL/InnoDB-4.0.6(2002 年 12 月 19 日)


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

7.5.16.18 MySQL/InnoDB-3.23.54(2002 年 12 月 12 日)


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

7.5.16.19 MySQL/InnoDB-4.0.5(2002 年 11 月 18 日)


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

7.5.16.20 MySQL/InnoDB-3.23.53(2002 年 10 月 9 日)


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

7.5.16.21 MySQL/InnoDB-4.0.4(2002 年 10 月 2 日)


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

7.5.16.22 MySQL/InnoDB-4.0.3(2002 年 8 月 28 日)


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

7.5.16.23 MySQL/InnoDB-3.23.52(2002 年 8 月 16 日)


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

7.5.16.24 MySQL/InnoDB-4.0.2(2002 年 7 月 10 日)


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

7.5.16.25 MySQL/InnoDB-3.23.51(2002 年 6 月 12 日)


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

7.5.16.26 MySQL/InnoDB-3.23.50(2002 年 4 月 23 日)


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

7.5.16.27 MySQL/InnoDB-3.23.49(2002 年 2 月 17 日)


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

7.5.16.28 MySQL/InnoDB-3.23.48(2002 年 2 月 9 日)


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

7.5.16.29 MySQL/InnoDB-3.23.47(2001 年 12 月 28 日)


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

7.5.16.30 MySQL/InnoDB-4.0.1(2001 年 12 月 23 日)


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

7.5.16.31 MySQL/InnoDB-3.23.46(2001 年 11 月 30 日)


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

7.5.16.32 MySQL/InnoDB-3.23.45(2001 年 11 月 23 日)


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

7.5.16.33 MySQL/InnoDB-3.23.44(2001 年 11 月 2 日)


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

7.5.16.34 MySQL/InnoDB-3.23.43(2001 年 10 月 4 日)


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

7.5.16.35 MySQL/InnoDB-3.23.42(2001 年 9 月 9 日)


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

7.5.16.36 MySQL/InnoDB-3.23.41(2001 年 8 月 13 日)


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

7.5.16.37 MySQL/InnoDB-3.23.40(2001 年 7 月 16 日)


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

7.5.16.38 MySQL/InnoDB-3.23.39(2001 年 6 月 13 日)


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

7.5.16.39 MySQL/InnoDB-3.23.38(2001 年 5 月 12 日)


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

7.5.17 InnoDB についての問い合わせ先

InnoDB エンジンの製造元である Innobase Oy の問い合わせ先は次のとおりです。 Web サイト: http://www.innodb.com/ 。 電子メール: sales@innodb.com

 
phone: 358-9-6969 3250 (office) 358-40-5617367 (mobile)
Innobase Oy Inc.
World Trade Center Helsinki
Aleksanterinkatu 17
P.O.Box 800
00101 Helsinki
Finland


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

7.6 BDB または BerkeleyDB テーブル

7.6.1 BDB テーブルの概要   
7.6.2 BDB のインストール   
7.6.3 BDB 起動オプション   
7.6.4 BDB テーブルの特性   
7.6.5 近い将来に修正する必要がある BDB の問題   
7.6.6 BDB でサポートされているオペレーティングシステム   
7.6.7 BDB テーブルの制限事項   
7.6.8 BDB テーブルを使用するときに起こりうるエラー   


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

7.6.1 BDB テーブルの概要

BerkeleyDB(http://www.sleepycat.com/ で入手可能)は、MySQL にトランザクションストレージエンジンをもたらしました。このストレージエンジンのサポートは、バージョン 3.23.34 から MySQL ソースディストリビューションに組み込まれるようになり、MySQL-Max バイナリでアクティブ化されます。通常、このストレージエンジンは略して BDB と呼ばれます。

BDB テーブルはクラッシュに対する耐久性が高く、トランザクションでの COMMIT および ROLLBACK 操作にも対応します。 MySQL ソースディストリビューションに付属する BDB ディストリビューションには、MySQL でより円滑に動作するための小規模なパッチがいくつか適用されています。 パッチが適用されていない BDB バージョンは、MySQL で使用できません。

MySQL AB は、Sleepycat 社と密接に協力しながら、MySQL/BDB インタフェースの品質維持に努めています。

BDB テーブルのサポートに関しては、ユーザによる問題の特定を支援すると共に、BDB テーブルが関係するあらゆる問題に対する再現可能なテストケースの作成を支援しています。作成されたテストケースは Sleepycat 社に送られ、同社の支援を受けながら問題を特定して修正します。このように 2 段階の作業になるため、BDB テーブルの問題は、他のストレージエンジンよりも修正に若干時間がかかる場合があります。 ただし、BerkeleyDB コード自体はこれまでに MySQL 以外の多くのアプリケーションで使用されているため、大きな問題が発生することは考えられません。 「1.4.1 MySQL AB によって提供されるサポート」 節 参照 。


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

7.6.2 BDB のインストール

BerkeleyDB をサポートする MySQL のバイナリバージョンをダウンロードした場合は、MySQL のバイナリバージョンをインストールするための指示に従ってください。 「2.2.9 MySQL バイナリディストリビューションのインストール」 節 参照 。 「4.8.5 mysqld-max(拡張 mysqld サーバ)」 節 参照 。

Berkeley DB をサポートする MySQL をコンパイルするには、MySQL バージョン 3.23.34 以降をダウンロードし、--with-berkeley-db オプションを使って MySQL をコンフィギャします。 「2.3 MySQL ソースディストリビューションのインストール」 節 参照 。

 
cd /path/to/source/of/mysql-3.23.34
./configure --with-berkeley-db

詳しい最新情報については、BDB ディストリビューション付属のマニュアルを参照してください。

Berkeley DB 自体は十分にテストされていて信頼できますが、MySQL とのインタフェースはまだガンマ品質と見なされています。 当社は、このインタフェースの 1 日も早い安定化を目指して、積極的に改善と最適化を行っています。


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

7.6.3 BDB 起動オプション

AUTOCOMMIT=0 で実行している場合、BDB テーブルでの変更は COMMIT を実行するまで反映されません。コミットの代わりに ROLLBACK を実行すると、変更が無効になります。 「6.7.1 START TRANSACTIONCOMMITROLLBACK の各構文」 節 参照 。

AUTOCOMMIT=1(デフォルト)で実行している場合は、変更が直ちにコミットされます。SQL コマンド BEGIN WORK で拡張トランザクションを開始できます。その場合、COMMIT を実行するまで(または変更の ROLLBACK を実行するまで)変更がコミットされません。

次に示す mysqld のオプションを使用すると、BDB テーブルの動作を変更できます。

オプション 説明
--bdb-home=directory BDB テーブルのベースディレクトリ。--datadir に使用するディレクトリと同じでなければならない。
--bdb-lock-detect=# Berkely のロック検出。DEFAULTOLDESTRANDOM、または YOUNGEST のいずれか。
--bdb-logdir=directory Berkeley DB のログファイルディレクトリ。
--bdb-no-sync ログを同期的にフラッシュしない。
--bdb-no-recover Berkeley DB をリカバリモードで起動しない。
--bdb-shared-data Berkeley DB をマルチプロセスモードで起動する(Berkeley DB を初期化する際に DB_PRIVATE を使用しない)。
--bdb-tmpdir=directory Berkeley DB のテンポラリファイルディレクトリ。
--skip-bdb BDB テーブルの使用を無効にする。
-O bdb_max_lock=1000 ロックの数の上限を設定する。 bdb_max_lock 節 参照 。

--skip-bdb を使用すると、MySQL は Berkeley DB ライブラリを初期化しなくなるため、大量のメモリを節約できます。このオプションを使用しているときは BDB テーブルを使用できません。BDB テーブルを作成しようとすると、代わりに MyISAM テーブルが作成されます。

BDB テーブルを使用する予定であれば、通常は --bdb-no-recover を指定せずに mysqld を起動する必要があります。ただし、BDB ログファイルが破損している場合に mysqld を起動しようとすると、問題が発生する可能性があります。 「2.4.2 MySQL サーバの起動に関する問題」 節 参照 。

bdb_max_lock では、BDB テーブルでアクティブにできるロックの最大数(デフォルトは 10,000)を指定できます。長いトランザクションを実行しているときや、mysqld がクエリの計算で大量のレコードを調べているときに、bdb: Lock table is out of available locks または Got error 12 from ... というエラーが発生する場合は、この数値を大きくしてください。

また、大規模なトランザクションを使用する場合は、binlog_cache_size および max_binlog_cache_size を変更することもできます。 「6.7.1 START TRANSACTIONCOMMITROLLBACK の各構文」 節 参照 。


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

7.6.4 BDB テーブルの特性


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

7.6.5 近い将来に修正する必要がある BDB の問題


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

7.6.6 BDB でサポートされているオペレーティングシステム

今のところ、BDB ストレージエンジンは次のオペレーティングシステムで動作することが確認されています。

次のオペレーティングシステムでは動作しません。

注意: 上記の一覧は完全ではありません。情報が入り次第更新する予定です。

BDB テーブルのサポート付きで MySQL をビルドする場合に、mysqld を起動するとログファイルに次のエラーが記録されることがあります。

 
bdb: architecture lacks fast mutexes: applications cannot be threaded
Can't init databases

これは、使用するアーキテクチャで BDB テーブルがサポートされていないことを意味します。 この場合は、BDB テーブルのサポートなしで MySQL をビルドし直す必要があります。


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

7.6.7 BDB テーブルの制限事項

次に挙げるのは、BDB テーブルを使用する場合の制限事項です。


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

7.6.8 BDB テーブルを使用するときに起こりうるエラー


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

2004年 10月 9日 texi2html にて作成