2009-05-03 28 views
40

データベースからの読み取りにトランザクションを使用することについては、非常に異なる意見があるようです。 developerWorksの記事Transaction strategies: Models and strategies overviewから読み取り専用DBアクセスのトランザクション?

引用:

は、なぜあなたはデータのみを読んでいる 場合、トランザクションを必要とするでしょうか?答えは ではありません。読み取り専用の 操作を実行するために トランザクションを開始すると 処理スレッドのオーバーヘッドが追加され、データベース(あなたが を使用しているデータベースの種類に に依存し、どのような分離レベルが設定されている上の共有 読み取りロックを引き起こす可能性があります から)。 Hibernateのドキュメントからの反対意見として

次の引用があるNon-transactional data access and the auto-commit mode

私たちの推薦は とき、読み取り専用トランザクションを適用するために、アプリケーションで 自動コミット・モードを使用しないことであり、 明白なパフォーマンス の利点があるか、または将来のコード変更 が非常に起こりそうもありません。常に 通常のACIDトランザクションを使用して、 データを読み取るかどうかに関係なく、 データアクセス操作 をグループ化することをお勧めします。

また、EclipseLinkメーリングリストhereにも同様の議論があります。

だからどこが真実ですか?ベストプラクティスを読むための取引ですか?どちらも実行可能なソリューションであれば、トランザクションを使用する基準は何ですか?

私の知る限り、分離レベルが 'read committed'よりも高い場合にのみ違いが見られます。これは正しいです?

どのような経験や推奨事項がありますか?

答えて

16

スティーブンDevijverは、トランザクションを開始するためのいくつかの理由を提供しました現在進行中のトランザクションがない場合は、クエリでも新しいトランザクションを開始する必要があります。たとえば、自動コミットモードを持つDBMSがあります(この文はトランザクションを開始し、文が完了すると直ちにコミットします)。他のDBMSは、デフォルトで文をアトミック(効果的に自動コミット)しますが、 'BEGIN WORK'などの文で明示的なトランザクションを開始し、次のCOMMITまたはROLLBACKまで自動コミットをキャンセルします(IBM Informix Dynamic ServerはデータベースがMODE ANSI)。

私はロールバックしないように助言することはできません。読取り専用トランザクションには何の違いもなく、DBAに迷惑をかける範囲でROLLBACKを回避する方がよいでしょう。しかし、COMMITを実行せずにプログラムが終了した場合、DBMSは不完全なトランザクションに対してROLLBACKを実行する必要があります(データベースを変更した場合や、データを選択した場合でも)。

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

8

デフォルトのタイムアウト以外のクエリに対して特定のタイムアウトを設定する場合、または分離レベルを変更する場合は、トランザクションは読み取り専用操作に必要です。

また、すべてのデータベース(例外について認識していないデータベース)は、クエリごとにトランザクションを内部的に開始します。ロールバックが必要ない場合、トランザクションをロールバックするのは一般的ではないと考えられています。

DBAがロールバック・アクティビティを監視している可能性があります。その場合、デフォルトのロールバック・ビヘイビアが問題になります。

したがって、トランザクションは、開始したかどうかに関係なく使用されます。必要がない場合は起動しないでください。ただし、読み取り専用操作ではロールバックは実行しないでください。

  • セットタイムアウトやロック・モード
  • 設定分離レベル

標準SQLが必要です。操作はデータベースのみを読んうとしている場合でも

8

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

常にトランザクションを使用する理由の1つは、保護の一貫性です。あなたが "必要な"ときにのみトランザクションを手動で宣言することでバイディングを開始すると、重要な時を忘れてしまいます。あるいは、読者が読んでいるだけのセットの操作が突然ではないというのは、後のプログラマーが、それが想定されていると気づいていなかったか、コードが隠された書き込みを持つ関数を呼び出すからです。たとえば、コマンドラインデータベースクライアントを自動コミットしないように構成します。つまり、私は指を削除しても、指を削除してロールバックすることができます。

指摘されているように、分離レベルがあります。これにより、他のプロセスが間にデータを書き込んで、読み込みを効果的にアトミックにすることができても心配することなく複数の読み込みを行うことができます。これは競合状態をデバッグする多くの時間からあなたを救うでしょう。

最後に、トランザクションを読み取り専用に設定できることがよくあります。これはあなたの前提をチェックし、何かが書き込もうとするとエラーになります。

Here's a nice article summing it all up.詳細はOracle固有ですが、概念は一般的です。

関連する問題