8

私は今日、いくつかの奇妙な行動に遭遇し、それが期待されているのか、それとも標準的なのか疑問に思いました。MySQL5に対してHibernateを使用しています。コーディングの過程で、トランザクションを閉じるのを忘れましたが、他の人が関係していると思います。

最終的にトランザクションを閉じ、コードを実行してテーブルを確認したところ、次のことに気づきました。トランザクションを閉じずに誤ってコードを実行したため、実際の行が挿入されなかったにもかかわらず、自動インクリメントの代理主キー値がインクリメントされたため、ギャップがありました(つまり、idフィールド値が751から762)。

これは予想される動作ですか、それとも標準的な動作ですか?データベースによって異なるのでしょうか?および/またはHibernate自身のトランザクション抽象化はこれに何らかの影響を与える可能性がありますか?

4

4 に答える 4

8

はい、それは予想されます。

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

Oracleのようなデータベースのシーケンスはほとんど同じように機能します。特定の値が要求されると、それがコミットされるかどうかは重要ではありません。再利用されることはありません。また、シーケンスも完全に順序付けられているわけではありません。

于 2009-09-09T14:12:29.353 に答える
6

それはかなり期待される振る舞いです。これがないと、dbは、レコードを挿入した各トランザクションが完了するのを待ってから、次の挿入に新しいIDを割り当てる必要があります。

于 2009-09-09T14:12:51.583 に答える
5

はい、これは予想される動作です。 このドキュメントはそれを非常によく説明しています。

5.1.22以降、同時トランザクションが自動インクリメント値を取得する方法を制御する3つの異なるロックモードが実際にあります。ただし、3つすべてにより、ロールバックされたトランザクションにギャップが生じます(ロールバックされたトランザクションで使用される自動インクリメント値は破棄されます)。

于 2009-09-09T14:14:10.693 に答える
0

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

ギャップがないようにしたい場合は、独自のストアド プロシージャを作成して、トランザクションで列を増やす必要がありますが、そのようなコードは他のトランザクションをブロックするため、注意が必要です。

SELECT CURRVAL FROM SEQUENCE_TABLE WHERE TYPE = :YOUR_SEQ_NAME FOR UPDATE; を実行します。UPDATE SEQUENCE_TABLE SET CURRVAL = :INCREMENTED_CURRVAL WHERE TYPE = :YOUR_SEQ.

于 2011-02-15T12:10:23.713 に答える