このページは機械翻訳したものです。
NDB Cluster には、トランザクションの処理に関していくつかの制限があります。 これらには、次のものが含まれます。
-
トランザクション分離レベル.
NDBCLUSTERストレージエンジンはREAD COMMITTEDトランザクション分離レベルのみをサポートします。 (たとえば、InnoDBはREAD COMMITTED、READ UNCOMMITTED、REPEATABLE READ、およびSERIALIZABLEをサポートします。)NDBはREAD COMMITTEDを行単位で実装する必要があることに注意してください。読取りリクエストが行を格納しているデータノードに到着すると、その時点で最後にコミットされたバージョンの行が返されます。コミットされていないデータが返されることはありませんが、複数の行を変更するトランザクションが同じ行を読み取るトランザクションと同時にコミットする場合、特定の行読取りリクエストを他のトランザクションのコミットの前または後に処理できるため、読取りを実行するトランザクションは、これらの間で異なる行に対して値の前、値の後、またはその両方を監視できます。
特定のトランザクションが変更前または変更後の値のみを読み取るようにするには、
SELECT ... LOCK IN SHARE MODEを使用して行ロックを設定します。 このような場合、ロックは、所有しているトランザクションがコミットされるまで保持されます。 行ロックを使用すると、次の問題が発生することもあります:ロック待機タイムアウトエラーの頻度の向上と同時実行性の低下
コミットフェーズを必要とする読取りによるトランザクション処理オーバーヘッドの増加
使用可能な同時ロック数を使い果たす可能性があり、
MaxNoOfConcurrentOperationsによって制限されています
NDBでは、LOCK IN SHARE MODEやFOR UPDATEなどの修飾子を使用しないかぎり、すべての読取りにREAD COMMITTEDが使用されます。LOCK IN SHARE MODEでは共有行ロックが使用され、FOR UPDATEでは排他行ロックが使用されます。 一意キー読取りでは、自己一貫性読取りを保証するためにNDBによってロックが自動的にアップグレードされます。BLOB読取りでは、一貫性のために追加ロックも使用されます。NDB のトランザクション分離レベルのクラスタ実装が
NDBデータベースのバックアップおよび復元に与える影響については、セクション23.5.8.4「NDB Cluster バックアップのトラブルシューティング」 を参照してください。 -
トランザクションと BLOB または TEXT カラム.
NDBCLUSTERは、MySQL から認識できるテーブルに MySQL のBLOBまたはTEXTデータ型のいずれかを使用するカラム値の一部のみを格納します。BLOBまたはTEXTの残りの部分は、MySQL からアクセスできない別の内部テーブルに格納されます。 これに関連して、これらの型のカラムを含むテーブルに対してSELECTステートメントを実行するときに常に注意すべき問題が 2 つ発生します。「NDB Cluster」テーブルからの
SELECTの場合:SELECTにBLOBまたはTEXTカラムが含まれている場合、READ COMMITTEDトランザクション分離レベルは読取りロック付きの読取りに変換されます。 これは一貫性を保証するために行われます。-
一意キーのルックアップを使用して
BLOBまたはTEXTデータ型のいずれかを使用するカラムを取得し、1 つのトランザクション内で実行されるSELECTの場合は、共有読み取りロックがトランザクションの期間中 (つまり、トランザクションがコミットまたは中止されるまで) そのテーブルに保持されます。インデックスまたはテーブルスキャンを使用するクエリーでは、
BLOBまたはTEXTカラムを含むNDBテーブルが対象であっても、この問題は発生しません。たとえば、次の
CREATE TABLEステートメントによって定義されたテーブルtについて考えます。CREATE TABLE t ( a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b INT NOT NULL, c INT NOT NULL, d TEXT, INDEX i(b), UNIQUE KEY u(c) ) ENGINE = NDB,tで次のクエリーを実行すると、一意キー検索が使用されるため、共有読取りロックが発生します:SELECT * FROM t WHERE c = 1;しかし、ここに示す 4 つのクエリーでは、いずれも共有読み取りロックは発生しません。
SELECT * FROM t WHERE b = 1; SELECT * FROM t WHERE d = '1'; SELECT * FROM t; SELECT b,c WHERE a = 1;その理由は、これら 4 つのクエリーのうち、1 つ目はインデックススキャンを使用し、2 つ目と 3 つ目はテーブルスキャンを使用し、4 つ目は (主キールックアップを使用していますが)
BLOBまたはTEXTカラムの値を取得していないためです。BLOBまたはTEXTカラムを取得する一意キールックアップを使用するクエリーを回避するか、このようなクエリーを回避できない場合はトランザクションのコミットをできるだけあとで行うようにすると、共有読み取りロックによる問題を最小限に抑えることができます。
-
一意キー参照とトランザクション分離. 一意インデックスは、内部的にメンテナンスされる非表示インデックステーブルを使用して
NDBに実装されます。 一意インデックスを使用してユーザーが作成したNDBテーブルにアクセスすると、非表示のインデックステーブルが最初に読み取られて主キーが検索され、次にユーザーが作成したテーブルの読取りに使用されます。 この二重読取り操作中にインデックスが変更されないように、非表示のインデックステーブルで検出された行はロックされます。 ユーザー作成のNDBテーブルの一意インデックスによって参照される行が更新されると、非表示のインデックステーブルには、更新が実行されるトランザクションによる排他ロックが適用されます。 つまり、同じ (ユーザーが作成した)NDBテーブルに対する読取り操作は、更新が完了するまで待機する必要があります。 これは、読取り操作のトランザクションレベルがREAD COMMITTEDの場合でも当てはまります。潜在的なブロッキング読取りをバイパスするために使用できる回避策の 1 つは、読取りの実行時に SQL ノードが一意のインデックスを無視するように強制することです。 これを行うには、テーブルを読み取る
SELECTステートメントの一部としてIGNORE INDEXインデックスヒントを使用します (セクション8.9.4「インデックスヒント」 を参照)。 MySQL サーバーでは、NDBで作成された一意のインデックスごとにシャドウ順序付きインデックスが作成されるため、かわりに順序付きインデックスを読み取ることができ、一意のインデックスアクセスロックが回避されます。 結果の読取りは、主キーによってコミットされた読取りと同じ一貫性があり、行の読取り時に最後にコミットされた値を返します。順序付けされたインデックスを介して読み取ると、クラスタ内のリソースの使用効率が低下し、待機時間が長くなる可能性があります。
一意の値ではなく範囲をクエリーすることで、アクセスに一意のインデックスを使用しないようにすることもできます。
-
ロールバック. 部分的なトランザクションおよびトランザクションの部分的なロールバックはありません。 重複キーまたは同様のエラーが発生すると、トランザクション全体がロールバックされます。
この動作は、個々のステートメントをロールバックできる
InnoDBなどのほかのトランザクション対応のストレージエンジンと異なります。 -
トランザクションとメモリー使用量. この章のほかの場所で説明されているように、NDB Cluster は大きなトランザクションを適切に処理しません。多数の操作を含む単一の大きなトランザクションを試みるよりも、少数の操作で多数の小さなトランザクションを実行することをお勧めします。 特に考慮すべき点は、大規模なトランザクションが非常に大量のメモリーを必要とすることです。 このため、次のリストで説明するように、多数の MySQL ステートメントのトランザクション動作が影響を受けます:
TRUNCATE TABLEは、NDBテーブルに対して使用した場合、トランザクションになりません。TRUNCATE TABLEでテーブルを空にできない場合は、成功するまでこれを再実行する必要があります。DELETE FROM(WHERE句が内場合も含む) は、トランザクションになります。 テーブルに非常に多くの行が含まれる場合は、複数のDELETE FROM ... LIMIT ...ステートメントを使用して削除操作を「ひとまとめに」すると、パフォーマンスが向上することがあります。 テーブルを空にすることが目的である場合は、代わりにTRUNCATE TABLEを使用することをお勧めします。-
LOAD DATA ステートメント.
NDBテーブルで使用する場合、LOAD DATAはトランザクション対応ではありません。重要LOAD DATAステートメントを実行すると、NDBエンジンは不規則な間隔でコミットを実行し、通信ネットワークの使用率を向上させます。 このようなコミットが発生するタイミングを事前に知ることはできません。 ALTER TABLE とトランザクション.
ALTER TABLEの一部としてNDBテーブルをコピーする場合、コピーの作成はトランザクションになりません。 (いずれにしても、コピーが削除されたときにこの操作はロールバックされます。)
トランザクションと COUNT() 関数. NDB Cluster レプリケーションを使用する場合、レプリカ上の
COUNT()関数のトランザクションの一貫性を保証することはできません。 つまり、ソースで単一トランザクション内のテーブルの行数を変更する一連のステートメント (INSERT、DELETE、またはその両方) を実行する場合、レプリカでSELECT COUNT(*) FROMクエリーを実行すると中間結果が生成されることがあります。 これは、tableSELECT COUNT(...)がダーティー読み取りを行うために発生し、NDBストレージエンジンのバグではありません。 (詳細は、Bug #31321 を参照してください。)