2009-09-09 17 views
8

今日、好奇心を抱くような動作が発生しました。 MySQL5に対してHibernateを使用しています。私はトランザクションを閉じるのを忘れてコーディングの過程で、私は他の人が関連付けることができると思います。コミットされていないデータベーストランザクションと自動インクリメント列

最後にトランザクションを終了し、コードを実行してテーブルをチェックしたところ、次のことに気付きました。私は間違ってトランザクションを閉じることなく私のコードを誤って実行したので、実際の行が挿入されることはありませんでしたが、自動インクリメント代用プライマリキーの値がインクリメントされたので、ギャップ(idフィールド値が751~762)。

これは予期される動作または標準動作ですか?それはデータベースによって異なるかもしれませんか?そして/またはHibernate自身のトランザクション抽象化はこれにいくつかの影響を及ぼすでしょうか?

+0

私は答えを知っていましたが、これはまだ興味深い質問です! – RichardOD

+1

理想的には、アプリケーション/デザインがシーケンスのギャップの影響を受けてはならないことです。これが実際に重要な状況になることは決してありません –

答えて

8

はい、そうです。

あなたはそれについて考える:データベースは他に何ができますか?列をインクリメントして、それを同じトランザクション内の他の挿入で外部キーとして使用すると、他の誰かがコミットしている間に、その値を使用することはできません。あなたはギャップを得るでしょう。

Oracleのようなデータベースのシーケンスは、同じように動作します。特定の値が要求されると、コミットされているかどうかは関係ありません。それは決して再利用されません。そして、シーケンスはあまりにも絶対に順序付けられていません。

6

これはかなりの動作です。それを使用すると、dbは、新しいIDを次の挿入に割り当てる前に、レコードを挿入した各トランザクションが完了するのを待たなければなりません。

5

はい、これは予想される動作です。 This documentationは非常によく説明しています。

5.1.22から、実際には、同時トランザクションが自動インクリメント値を取得する方法を制御する3つの異なるロックモードがあります。しかし、3つすべてがロールバック・トランザクションのためのギャップを引き起こします(ロールバックされたトランザクションによって使用される自動インクリメント値は捨てられます)。

0

データベース配列は、ギャップのないid配列を保証するものではありません。これらはトランザクションに依存しないように設計されており、そのような方法でのみ非ブロッキングにすることができます。あなたは何のギャップを望んでいない

、あなたはcarrefullでなければならないので、トランザクションの列を増やすことが、そのようなコードは、他のトランザクションをブロックします独自のストアドプロシージャを記述する必要があります。

あなたはSELECT CURRVAL FROM SEQUENCE_TABLE WHERE TYPE =:YOUR_SEQ_NAME FOR UPDATEを実行します。 UPDATE SEQUENCE_TABLE SET CURRVAL =:INCREMENTED_CURRVAL WHERE TYPE =:YOUR_SEQです。

関連する問題