61

データベースからの読み取りにトランザクションを使用することについては、非常に異なる意見があるようです。

DeveloperWorks の記事「トランザクション戦略: モデルと戦略の概要」からの引用:

データを読み取るだけの場合、なぜトランザクションが必要になるのでしょうか? 答えは、そうではないということです。トランザクションを開始して読み取り専用操作を実行すると、処理スレッドのオーバーヘッドが増加し、データベースで共有読み取りロックが発生する可能性があります (使用しているデータベースの種類と分離レベルの設定によって異なります)。

反対の意見として、Hibernate のドキュメントからの次の引用があります。非トランザクション データ アクセスと自動コミット モード

アプリケーションで自動コミット モードを使用しないこと、およびパフォーマンス上の明らかな利点がある場合、または将来のコード変更の可能性が非常に低い場合にのみ、読み取り専用トランザクションを適用することをお勧めします。データの読み取りまたは書き込みに関係なく、常に通常の ACID トランザクションを優先して、データ アクセス操作をグループ化します。

ここの EclipseLink メーリング リストでも同様の議論が行われています。

では、真実はどこにあるのでしょうか?ベスト プラクティスを読み取るためのトランザクションかどうか。両方とも実行可能なソリューションである場合、トランザクションを使用する基準は何ですか?

私が見る限り、分離レベルが「コミットされた読み取り」よりも高い場合にのみ違いがあります。これは正しいです?

体験談とおすすめは?

4

3 に答える 3

29

Steven Devijverは、操作がデータベースの読み取りのみを行う場合でも、トランザクションを開始するためのいくつかの正当な理由を提供しました。

  • タイムアウトまたはロックモードを設定する
  • 分離レベルを設定する

標準SQLでは、現在進行中のトランザクションがない場合は、クエリでも新しいトランザクションを開始する必要があります。それが起こらないDBMSがあります。たとえば、自動コミットモードのDBMSがあります(ステートメントはトランザクションを開始し、ステートメントが完了するとすぐにコミットします)。他のDBMSは、デフォルトでステートメントをアトミック(事実上自動コミット)にしますが、「BEGIN WORK」などのステートメントで明示的なトランザクションを開始し、次のCOMMITまたはROLLBACKまで自動コミットをキャンセルします(IBM Informix Dynamic Serverはそのようなものです-データベースがMODEでない場合) ANSI)。

ロールバックしないようにアドバイスするかどうかはわかりません。読み取り専用トランザクションに違いはなく、DBAを煩わせる範囲で、ROLLBACKを回避することをお勧めします。ただし、プログラムがCOMMITを実行せずに終了した場合、DBMSは、データベースを変更した場合、および(簡単にするために)データのみを選択した場合でも、不完全なトランザクションに対してロールバックを実行する必要があります。

全体として、一連の操作のデフォルトの動作を変更する場合は、トランザクションが読み取り専用であっても、トランザクションを使用します。デフォルトの動作に満足している場合は、トランザクションを使用することは重要ではありません。コードをDBMS間で移植できるようにする場合は、トランザクションが必要であると想定するのが最善です。

于 2009-05-03T22:08:11.557 に答える
16

まず、これは時期尚早の最適化のように思えます。Steven が指摘したように、ほとんどの健全なデータベースはとにかくトランザクションを開始し、実際に行っているのは各ステートメントの後に commit を呼び出すことだけです。したがって、その観点からは、各ステートメントが新しいトランザクションを開始する必要があるため、自動コミットのパフォーマンスが低下する可能性があります。またはそうでないかもしれません。ベンチマークだけがそれを教えてくれますが、それがあなたのアプリケーションにわずかな違いをもたらさないことは間違いありません。

常にトランザクションを使用する理由の 1 つは、保護の一貫性です。「必要な」ときにのみトランザクションを手動で宣言することにいじり始めると、重要な時期に忘れてしまいます。または、読み取り専用であると思われる一連の操作が突然そうではなくなります。これは、後のプログラマーがそれが想定されていることに気付かなかったか、コードが隠し書き込みを持つ関数を呼び出しているためです。たとえば、コマンド ライン データベース クライアントを自動コミットしないように構成しています。これは、削除クエリをファット フィンガーしてもロールバックできることを意味します。

指摘されているように、分離レベルがあります。これにより、他のプロセスがその間にデータに書き込んだかどうかを心配することなく、複数の読み取りを実行できるため、読み取りが効果的にアトミックになります。これにより、競合状態のデバッグに何時間も費やす必要がなくなります。

最後に、多くの場合、トランザクションを読み取り専用に設定できます。これにより、仮定がチェックされ、何かを書き込もうとするとエラーが発生します。

ここにすべてをまとめた素晴らしい記事があります。 詳細は Oracle 固有ですが、概念は一般的なものです。

于 2009-05-03T22:32:12.873 に答える