2017-02-05 6 views
4

私は、値のタプルをランダムな方法でランダムUUIDと接続する方法を探しています。並行性の制約のためにトランザクションに失敗する可能性はありません。SQLマージをアトミックに実行する方法はありますか?

私が編集する必要があるテーブルには、UUIDで記述されるべきいくつかの値が含まれています。この例では、テーブルの名前はfooで、2つの文字列barquxが1つのフィールドuuidを指すことが宣言されています。 (bar, qux)は、テーブル全体で一意である必要があります。 UUIDは本質的にユニークです。

は、SQLは、(オラクル部12cを使用して)アトミックに次のようなことが可能である場合、私は疑問に思う:私のデータベースクエリの結果

MERGE INTO foo a 
    USING (SELECT bar, qux FROM foo b 
    ON b.bar = 'a' and b.qux = 'b' 
WHEN NOT MATCHED THEN INSERT (a.bar, a.qux, a.uuid) 
    VALUES ('a', 'b', 'some-uuid'); 

SELECT uuid FROM foo WHERE bar = 'a' and qux = 'b'; 

を、私は(bar, qux)はランダムなUUIDと接続するためのタプルをしたいです。このUUIDは同時トランザクションで同じでなければならず、別の(ランダムな)UUIDを同時に挿入するため、競合するリクエストが失敗することはありません。

バックグラウンドとして:これらの挿入は、大部分が互いに独立しているが、値が一致していてはならないこの共有識別テーブルを持つ、かなり長期間実行されるトランザクションの一部です。多くのプログラミング言語がCASを提供していますが、これは私がこの場合に行っていることですが、SQLのsmilar機能についてはわかりません。一案として

ダーティを読み込みを可能にするかどうかは疑問(コミットされていないが、分離レベルを読み出す)溶液であるが、MERGE文がアトミックこの場合の他のトランザクションに表示されているかどうかは分からないであろう。(これはOracleでは不可能です)。データベースはJDBC経由でアクセスされますが、潜在的に複数のVMノードからアクセスされます。

+2

Oracleはコミットされていない読み取りを許可しません –

+0

どのくらいの頻度で衝突が頻繁に発生すると思われますか?それほど頻繁ではない場合は、no_data_foundが自律型トランザクションを実行して挿入を試みる関数を呼び出して、テーブルを照会する関数である(bar、qux)に一意制約を置くことができます。再試行カウント)を使用して衝突を処理します。 –

+0

長時間実行されるトランザクションは、これまで使用してきたRDBMSでは明確なノー・ノーです。 –

答えて

1

AUTONOMOUS_TRANSACTIONプラグマで定義されたPL/SQLファンクションにMERGEおよびSELECT文をカプセル化できます。

別のセッションで同じUUIDが挿入されたために一意の制約違反が発生した場合、その関数で例外をキャッチしてUUIDを選択して戻すことができます。

このようにして、MERGE命令は、(関数が実行されている限り)短時間だけレコードをロックし、アプリケーションが別のトランザクションで実行され、現在のトランザクションを推論しません。唯一の制約違反の場合のエラー処理

2

トランザクションがコミットされた後にのみ挿入が表示されるため、長期実行トランザクションからは実行できません。

あなたが行う必要があるのは、アプリケーションレイヤーから新しいトランザクションを開き、次にMERGEまたはUPSERTに移動することです。このように、MERGE/UPSERTのアトミック性は、発行するセカンダリ・トランザクションによって保証されます。このようにして、セカンダリトランザクションがコミットされると、READ_COMMITTEDでは実行されているがSERIALIZABLEでは実行されていない場合、長期実行トランザクションに変更が反映されます。

同様のアプローチが、HibernateのTABLEベースの識別子となります。 this articleで詳細を読むことができます。

+0

私はこれをテストしましたが、トランザクションを並行して実行すると効果的です。結局のところ、私は生のデータテーブルにデータを消費し、潜在的な競合なしにuuidsを割り当てる専用の単一作業者を持つことがはるかに高速な選択肢であることを見出しました。 –

関連する問題