web-dev-qa-db-ja.com

読み取り専用DBアクセスのトランザクション?

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

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

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

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

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

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

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

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

経験と推奨事項は何ですか?

48
jbandi

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

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

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

ロールバックしないようにというアドバイスについてはわかりません。これは、読み取り専用トランザクションには影響を与えません。また、DBAを不快にさせる程度であれば、ROLLBACKを回避することをお勧めします。しかし、プログラムがCOMMITを実行せずに終了する場合、DBMSは不完全なトランザクションに対してROLLBACKを実行する必要があります。データベースを変更した場合はもちろん、(単純にするために)データのみを選択した場合でも同様です。

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

22

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

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

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

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

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

11
Schwern

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

また、すべてのデータベース-例外について知らない-は、各クエリのトランザクションを内部で開始します。一般に、そのロールバックが必要ない場合は、トランザクションをロールバックしないと見なされます。

DBAはロールバックアクティビティを監視している可能性があり、その場合、デフォルトのロールバック動作はそれらを困らせます。

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

10
Steven Devijver