Documentation Home
MySQL 5.6 リファレンスマニュアル
Download this Manual
EPUB - 7.5Mb
HTML Download (TGZ) - 7.2Mb
HTML Download (Zip) - 7.2Mb


13.2.5.2 INSERT DELAYED 構文

INSERT DELAYED ...

INSERT ステートメントの DELAYED オプションは、特定の種類のテーブル (MyISAM など) に使用できる、標準 SQL への MySQL 拡張です。クライアントが INSERT DELAYED を使用すると、サーバーからはただちに了解が得られ、行は、そのテーブルがほかのどのスレッドによっても使用されていないときに挿入されるようにキューに入れられます。

注記

INSERT DELAYED は、そのテーブルがほかで使用されていなければ、通常の INSERT より低速です。また、サーバーが、遅延された行が存在するテーブルごとに個別のスレッドを処理するための追加のオーバーヘッドもあります。つまり、INSERT DELAYED は、それが必要なことを実際に確信している場合にのみ使用するようにしてください。

MySQL 5.6.6 現在、INSERT DELAYED は非推奨であり、将来のリリースで削除されます。代わりに INSERT (DELAYED を付けない) を使用してください。

キューに入れられた行は、テーブルに挿入されるまで、メモリー内にのみ保持されます。つまり、mysqld を強制的に (たとえば、kill -9 で) 終了した場合や、mysqld が予期せず終了した場合は、まだディスクに書き込まれていないキューに入れられたすべての行が失われます

DELAYED の使用には、次のいくつかの制約があります。

  • INSERT DELAYED は、MyISAMMEMORYARCHIVE、および BLACKHOLE テーブルでのみ機能します。DELAYED をサポートしていないエンジンの場合は、エラーが発生します。

  • 挿入は、ロックを保持するセッションではなく、別のスレッドによって処理される必要があるため、LOCK TABLES を使用してロックされたテーブルで使用された場合は、INSERT DELAYED に対してエラーが発生します。

  • MyISAM テーブルでは、データファイルの途中に空きブロックが存在しない場合は、並列 SELECT および INSERT ステートメントがサポートされます。これらの状況では、MyISAMINSERT DELAYED を使用する必要はほとんどありません。

  • INSERT DELAYED は、値リストを指定する INSERT ステートメントでのみ使用するようにしてください。サーバーは、INSERT ... SELECT または INSERT ... ON DUPLICATE KEY UPDATE ステートメントでの DELAYED を無視します。

  • INSERT DELAYED ステートメントはただちに復帰するため、行が挿入される前に、LAST_INSERT_ID() を使用して、このステートメントによって生成される可能性のある AUTO_INCREMENT 値を取得することはできません。

  • DELAYED 行は、実際に挿入されるまで、SELECT ステートメントには表示されません。

  • MySQL 5.6 より前は、ステートメントが複数の行を挿入し、バイナリロギングが有効になっており、かつグローバルロギング形式がステートメントベースである (つまり、binlog_formatSTATEMENT に設定されているときは必ず) 場合、INSERT DELAYED は通常の INSERT として処理されました。MySQL 5.6 からは、binlog_format の値が STATEMENT または MIXED である場合は必ず、INSERT DELAYED は常に、単純な (つまり、DELAYED オプションのない) INSERT として処理されます。(後者の場合、このステートメントは行ベースのロギングへの切り替えをトリガーしなくなったため、そのステートメントベースの形式を使用してログに記録されます。)

    これは、行ベースのバイナリロギングモードを使用している (binlog_formatROW に設定されている) 場合は適用されません。この場合、INSERT DELAYED ステートメントは常に、指定のとおりに DELAYED オプションを使用して実行され、行更新イベントとしてログに記録されます。

  • INSERT DELAYED がスレーブ上で通常の INSERT として処理されるように、DELAYED はスレーブレプリケーションサーバー上で無視されます。これは、DELAYED のために、スレーブにマスターとは異なるデータが存在することになる場合があるためです。

  • テーブルが書き込みロックされているときに、そのテーブル構造を変更するために ALTER TABLE が使用されると、保留中の INSERT DELAYED ステートメントは失われます。

  • INSERT DELAYED は、ビューではサポートされません。

  • INSERT DELAYED は、パーティション化されたテーブルではサポートされません。

次に、INSERT または REPLACE に対して DELAYED オプションを使用したときの動作について詳細に説明します。この説明では、スレッドINSERT DELAYED ステートメントを受信したスレッドであり、ハンドラは、特定のテーブルに対するすべての INSERT DELAYED ステートメントを処理するスレッドです。

  • スレッドがあるテーブルに対する DELAYED ステートメントを実行すると、そのテーブルに対するすべての DELAYED ステートメントを処理するためのハンドラスレッドが作成されます (このようなハンドラがまだ存在しない場合)。

  • このスレッドは、そのハンドラが以前に DELAYED ロックを取得したかどうかをチェックします。取得していない場合は、それを行うようハンドラスレッドに指示します。DELAYED ロックは、ほかのスレッドがそのテーブルに対する READ または WRITE ロックを保持している場合でも取得できます。ただし、ハンドラはテーブル構造を確実に最新の状態にするために、すべての ALTER TABLE ロックまたは FLUSH TABLES ステートメントが完了するのを待機します。

  • このスレッドは INSERT ステートメントを実行しますが、行をテーブルに書き込む代わりに、最終行のコピーをそのハンドラスレッドによって管理されているキューに配置します。構文エラーはすべてスレッドによって検出され、クライアントプログラムにレポートされます。

  • INSERT は挿入操作が完了する前に復帰するため、クライアントは重複した行の数や、結果として得られる行の AUTO_INCREMENT 値をサーバーから取得できません。(C API を使用している場合も、同じ理由で、mysql_info() 関数は意味のある情報を何も返しません。)

  • バイナリログは、行がテーブルに挿入されたときにハンドラスレッドによって更新されます。複数行の挿入の場合、バイナリログは、先頭行が挿入されたときに更新されます。

  • delayed_insert_limit 行が書き込まれるたびに、ハンドラは、いずれかの SELECT ステートメントが引き続き保留中かどうかをチェックします。保留中の場合は、続行する前に、これらの実行を許可します。

  • ハンドラのキューにそれ以上行がなくなると、テーブルはロック解除されます。新しい INSERT DELAYED ステートメントが delayed_insert_timeout 秒以内に受信されなかった場合、ハンドラは終了します。

  • 特定のハンドラキュー内で delayed_queue_size を超える行が保留中である場合、INSERT DELAYED を要求しているスレッドは、そのキューに空きができるまで待機します。これは、遅延されたメモリーキューのすべてのメモリーが mysqld によって使用されてしまわないようにするために行われます。

  • このハンドラスレッドは、MySQL プロセスリストの Command カラム内に delayed_insert として現れます。これは、FLUSH TABLES ステートメントを実行するか、または KILL thread_id で強制終了すると強制終了されます。ただし、終了する前に、まずキューに入れられたすべての行をテーブルに格納します。この時間中は、ほかのスレッドからの新しいどの INSERT ステートメントも受け入れません。このあとに INSERT DELAYED ステートメントを実行すると、新しいハンドラスレッドが作成されます。

    つまり、実行中の INSERT DELAYED ハンドラが存在する場合、INSERT DELAYED ステートメントは通常の INSERT ステートメントより高い優先度を持っています。その他の更新ステートメントは、INSERT DELAYED キューが空になるか、だれかが (KILL thread_id で) このハンドラスレッドを終了するか、またはだれかが FLUSH TABLES を実行するまで待機する必要があります。

  • 次のステータス変数は、INSERT DELAYED ステートメントに関する情報を提供します。

    ステータス変数 意味
    Delayed_insert_threads ハンドラスレッドの数
    Delayed_writes INSERT DELAYED で書き込まれた行数
    Not_flushed_delayed_rows 書き込みを待機している行数

    これらの変数は、SHOW STATUS ステートメントを発行するか、または mysqladmin extended-status コマンドを実行することによって表示できます。


User Comments
  Posted by on November 27, 2005
I found that on an empty table in an unloaded MySQL instance, insert delayed was actually about 30% slower than plain insert! Batching multiple inserts into a single 'insert values' call seems to be more effective as a speedup. Results may vary on a busy database.
  Posted by Peter Laursen on November 18, 2008
A consequence of the INSERT being executed in another thread is that LOCK TABLE tbl WRITE is not compatible with INSERT DELAYED ..., see
lock table lt2 write;
insert delayed into lt2 (t) values ('123');
-- Error Code : 1165
-- INSERT DELAYED can't be used with table 'lt2' because it is locked with LOCK TABLES
  Posted by Marcin Szalowicz on November 30, 2012
There is one thing that is missing in the docs.
INSERT DELAYED is treated as normal INSERT if a column has defined TRIGGER (AFTER or BEFORE INSERT).
I found a bug about that and some comment regarding missing doc info, about this behaviour: http://bugs.mysql.com/bug.php?id=32220
Sign Up Login You must be logged in to post a comment.