Documentation Home
MySQL 5.6 リファレンスマニュアル
Download this Manual
PDF (US Ltr) - 26.8Mb
PDF (A4) - 26.9Mb
HTML Download (TGZ) - 7.2Mb
HTML Download (Zip) - 7.2Mb


MySQL 5.6 リファレンスマニュアル  /  ...  /  トランザクションおよびアトミック操作の違い

1.7.2.3 トランザクションおよびアトミック操作の違い

MySQL Server (バージョン 3.23-max およびすべてのバージョン 4.0 以降) では、InnoDB トランザクションストレージエンジンでトランザクションがサポートされています。MySQL 5.5 以上では、セクション14.1.1「デフォルトの MySQL ストレージエンジンとしての InnoDB」で説明しているように、新しく作成したテーブルではデフォルトで InnoDB が使用されます。デフォルトで、InnoDB完全な ACID コンプライアンスを提供します。ACID コンプライアンスと raw パフォーマンスとのバランスを取るように設定を調整する方法については、セクション14.2.1「MySQL および ACID モデル」を参照してください。トランザクションエラーの取り扱いにおける、標準 SQL と InnoDB との違いについては、セクション14.19.4「InnoDB のエラー処理」を参照してください。

MySQL Server での非トランザクションストレージエンジン (MyISAM など) は、アトミック操作と呼ばれるデータ整合性に関する別のパラダイムに従います。MyISAM テーブルは実質上常に、autocommit = 1 モードで操作します。変更されたデータは、一度に 1 つのステートメントでディスクに書き込まれるため、一連の関連する DML 操作は途中で妨害される可能性があり、この操作の一貫性を保証することが非常に困難になります。したがって、このモードは読み取りが大半のワークロードに適しています。トランザクションの条件では、それぞれの特定の更新が実行している間、ほかのユーザーがこれを妨げることができず、自動的なロールバックが存在できず、ダーティー読み取りが存在しません。ただし、これらの特性は単一の操作に適用され、一つの単位として成功または失敗する関連した更新には適用されません。LOCK TABLES ステートメントなどの回避策は、非トランザクションテーブルへの並列書き込みアクセスを制限します。

同じアプリケーション内の別々のテーブルの場合でも、どちらのパラダイムを使用するかを選択できます。信頼性と高いパフォーマンスを両立させる場合にはトランザクション機能を、(たとえばレプリケーションスレーブサーバーでの) 重要でない読み取りが大半のデータにはアトミック操作を選択できます。

InnoDB などのトランザクションストレージエンジンでは、負荷のかかる読み取り/書き込みワークロードに対する高い信頼性をサポートする多くの重要な機能が用意されています。結果として、トランザクションテーブルのメモリーおよびディスク容量の要件は高くなり、CPU オーバーヘッドが大きくなります。MySQL Server のモジュラー設計によって、さまざまなストレージエンジンの並列使用が可能になり、さまざまな要件に適合し、あらゆる状況で最適なパフォーマンスを実現できます。

非トランザクションテーブルでの信頼性に対する回避策

しかし、非トランザクションの MyISAM テーブルとの完全性も維持するには、MySQL Server の機能をどのように使用すればよいでしょうか。また、このような機能はトランザクションストレージエンジンにどのように匹敵するでしょうか。

  • 重大な状況で COMMIT ではなく ROLLBACK の呼び出しに依存するようにアプリケーションが作成されている場合、トランザクションの方が便利です。トランザクションでは、完了していない更新や失敗したアクティビティーがデータベースにコミットされていないことも確認します。サーバーには、自動ロールバックを行う機会が与えられ、データベースは保存されます。

    非トランザクションテーブルを使用する場合は、更新の前にチェックを含めることや、不整合についてデータベースをチェックし、このような不整合が発生した場合には自動的に修復または警告するスクリプトを実行することによって、アプリケーションレベルで潜在的な問題を解決する必要があります。MySQL ログを使用するか、さらに 1 つのログを追加することになっても、データの完全性を損なわずに、通常どおりテーブルを修正できます。

  • 場合によっては、重要なトランザクション更新は、アトミックになるように書き換えることができます。LOCK TABLES またはアトミック更新で複数の DML 操作を行うことができ、並列書き込みアクセスを制限することによってデッドロックが起こらないようにします。テーブルの末尾での並列挿入を可能にする、テーブルに対する READ LOCAL ロック (書き込みロックの反対) を取得した場合、読み取りは許可され、ほかのクライアントによる挿入も許可されます。新しく挿入したレコードは、読み取りがロックされているクライアントには、読み取りロックが解除されるまで表示されません。INSERT DELAYED を使用すると、ロックが解除されるまで挿入をローカルキューに入れることができ、クライアントは挿入が完了するまで待機する必要はありません。セクション8.10.3「同時挿入」およびセクション13.2.5.2「INSERT DELAYED 構文」を参照してください。

  • MySQL Server で安全性を確保するには、使用するテーブルの種類に関係なく、定期的にバックアップを作成してバイナリロギングをオンにします。使用するデータベースシステムに関係なく、どのような場合でもバックアップを作成することは賢明です。

次に、非トランザクションテーブルを操作するための手法を示します。

  • LOCK TABLES を使用して、通常はトランザクションを必要とするループをコード化することができ、実行中にレコードを更新するカーソルが不要です。

  • ROLLBACK を使用しないようにするため、次の方法を使用することができます。

    1. LOCK TABLES を使用して、アクセスするすべてのテーブルをロックします。

    2. 更新を実行する前に、true になっている必要がある条件をテストします。

    3. 条件が満たされていれば、更新します。

    4. UNLOCK TABLES を使用して、ロックを解除します。

    注記

    この解決方法は、だれかが更新の途中でスレッドを強制終了したときの状況に対処しません。その場合、すべてのロックが解除されますが、一部の更新が実行されていない可能性があります。

  • 次の手法を使用して、関数を用いて単一の操作でレコードを更新することもできます。

    • 現在の値に関連してカラムを変更します。これにより、別のクライアントがその間にカラム値を変更した場合でも、更新は正しくなります。

    • 実際に変更されたカラムのみを更新します。これが一般的にデータベースにとって適切な方法になります。

  • 一意の識別子を管理するときに、AUTO_INCREMENT カラムと、LAST_INSERT_ID() SQL 関数または mysql_insert_id() C API 関数のどちらかを使用することによって、LOCK TABLESROLLBACK などのステートメントを回避できます。セクション12.14「情報関数」およびセクション23.7.7.37「mysql_insert_id()」を参照してください。

    行レベルロックが必要な状況では、InnoDB テーブルを使用します。それ以外の場合、MyISAM テーブルでは、テーブルでフラグカラムを使用して、次のような操作を実行することができます。

    UPDATE tbl_name SET row_flag=1 WHERE id=ID;

    レコードが見つかり、元の行で row_flag がすでに 1 でなくなっていた場合、MySQL は、影響を受けた行の数として 1 を返します。MySQL Server が前述のステートメントを次のように変更したと考えることができます。

    UPDATE tbl_name SET row_flag=1 WHERE id=ID AND row_flag <> 1;