web-dev-qa-db-ja.com

データベーストランザクション-どのように機能しますか?

私はデータベーストランザクションについてもっと知りたいと思っています。トランザクションを書くためのACIDの経験則を見つけ、いくつかの質問を考えました。

ACIDの経験則:

トランザクションは次のようにする必要があります。

  1. アトミック-これは1つの作業単位であり、前後のトランザクションに依存しません。
  2. 一貫性-データはコミットまたはロールバックされ、何かが更新された場合と更新されていない場合の「中間」のケースはありません。
  3. 分離-現在のトランザクションの中間結果を表示するトランザクションはありません。
  4. 耐久性-システムが直後にクラッシュした場合でも、データがコミットされていれば、値は保持されます。

それらが内部でどのように機能するのか疑問に思っていたので、そのようなトランザクションを作成するときに考慮する必要がある要素をよりよく理解できます。具体的な詳細は、利用可能なデータベースの実装によって異なると思いますが、特定のルールは常に適用されます。

  1. アトミックルールをサポートしながら、データベースはどのように同時トランザクションを処理しますか?
    • 順番に処理されるトランザクションのキューはありますか?
    • 他のすべてを妨げている長いトランザクションはどのように処理されますか?
  2. テーブルの更新はメモリ内で行われるので、コミット前にクラッシュが発生した場合、データベースに変更はありませんか?
    • または、そのようなクラッシュに耐えるために更新される中間テーブルがいくつかありますか?
  3. トランザクションの進行中に、影響を受けるテーブルへのすべての読み取りおよび書き込みアクセスが防止されますか?
    • または、データベースは書き込みを許可しますが、トランザクションはコミット時にすべての変更を上書きしますか?
36
fletcher
  1. トランザクションキューイング、楽観的同時実行制御など、さまざまな方法があります。これは実際には非常に複雑な質問であり、それについて書かれた本があります。

    http://www.Amazon.co.uk/Databases-Transaction-Processing-Application-Oriented-Approach/dp/0201708728/ref=sr_1_3?ie=UTF8&s=books&qid=1281609705&sr=8-

  2. これは、データベースへのロギングのレベルによって異なります。厳密な先行書き込みログが保持されている場合、システムクラッシュが発生した場合、データベースは一貫性のある状態に戻されます。

  3. 並行性のタイプによって異なります。楽観的同時実行性にはロックは含まれませんが、トランザクションが終了した後でデータベースの状態が変更された場合、データベースは破棄されて再開されます。これにより、衝突がまれなデータベースの速度を上げることができます。また、行、テーブル、さらにはデータベース全体など、さまざまなレベルのロックがあります。

これらは非常に複雑な質問です。完全に答えられるようにしたい場合は、本を購入するか、並行システムの講義シリーズに参加することをお勧めします:-)

15
fredley

あなたの定義に関するいくつかの落とし穴:

アトミック-これは1つの作業単位であり、前後のトランザクションに依存しません。

アトミック性のより正確な定義では、「前または後」のトランザクションについては言及されていません。 Atomicityは、それ自体が実行する単一のトランザクションのプロパティです。つまり、最終的なカウントダウンでは、すべてのアクションが持続するか、まったく持続しないかのいずれかです。言い換えれば、「トランザクションの半分だけ」が持続することを許可されているわけではありません。

ただし、この概念は、ネストされたトランザクション、セーブポイント、およびユーザーが取得したセーブポイントまでの明示的なロールバックを要求する機能などの概念によって曖昧になっています。これらは、ある意味で、明示的なユーザーの要求にかかわらず、「トランザクションのアクションの半分だけ」が持続することを可能にします。

一貫性-データはコミットまたはロールバックされ、何かが更新された場合と更新されていない場合の「中間」のケースはありません。

この解釈は完全に間違っています。一貫性とは、トランザクションプロセッサ(この場合はDBMSエンジン)がシステム(データベース)を、システム(トランザクションプロセッサ)が認識している宣言された制約に違反した状態のままにできないことを意味します。たとえば、「データベースシステムの概要」の第16章を参照してください。

分離-現在のトランザクションの中間結果を表示するトランザクションはありません。

Nitpicking:トランザクションなし現在以外中間状態(状態、実際には結果ではない)を表示できます。さらに、トランザクション処理エンジンの「分離レベル」は、通常、Iプロパティに違反する可能性のある程度を定義することに注意してください。

耐久性-システムが直後にクラッシュした場合でも、データがコミットされていれば、値は保持されます。

ただし、このプロパティも、ネストされたトランザクションの可能性によって少しぼやけています。内部トランザクションがコミットして完了した場合でも、含まれているトランザクションは、それ自体で完全にロールバックしてそのコミットを元に戻すことができます。

10
Erwin Smout

実際の詳細は、おそらくそれがどのDBサーバーであるかによって多少異なりますが、この記事はあなたにとって興味深いかもしれません: トランザクション処理に関するチートシート

6
Hans Olsson

実装に関しては、[〜#〜] acid [〜#〜]の各プロパティを保証するための不均衡な取り組みがあります。私はそれを私の単純化した考えに要約することができます:

  • [〜#〜] a [〜#〜]張性は、最終的にはロックまたは他のアトミック操作に依存して、トランザクション内で変更されたデータをスワップします([〜共有ビューの元のデータを使用した#〜] i [〜#〜]solation)。

    アトミックルールをサポートしながら、データベースはどのように同時トランザクションを処理しますか?

    [〜#〜] i [〜#〜]solationを参照してください。

  • [〜#〜] c [〜#〜]一貫性はより基本的な[〜#〜] a [〜#〜]tomicityおよび[〜#〜] i [〜#〜]solationプロパティであり、本質的にデータベースサービスに属するのではなく、アプリケーション層にまで拡張されます。

    ルールの確保([〜#〜] a [〜#〜]張性および[〜#〜] i [〜#〜]分離が行われている)変更されたデータに対してそれらを実行することにより、かなり簡単です。

    これはspark哲学的議論です。しかし、私の意見では、重要なケースでは、最終的にコミットされる前の関連データ全体のすべての条件の検証は、アプリケーションロジック全体またはアプリケーションで実装できます-データベース固有にしないデータベース層の特定の手順。データベースサービスが保証しなければならない最低限のことは、以前に書き込まれたデータをエラーなしで読み取ることができることです。

    テーブルの更新はメモリ内で行われるので、コミット前にクラッシュが発生した場合、データベースに変更はありませんか?

    [〜#〜] i [〜#〜]solationを参照してください。

    [〜#〜] c [〜#〜][〜#〜] acid [〜#〜]の一貫性に注意してくださいは純粋に論理的で静的であり、後でCAP定理によって提案されるデータ伝搬関連のレベルまたはグレードはありません。

  • [〜#〜] i [〜#〜]分離は、最初に元のデータのコピーを変更することによって(共有ビューに変更をコミットする前に)普遍的に実現されます。

    トランザクションの進行中に、影響を受けるテーブルへのすべての読み取りおよび書き込みアクセスが防止されますか?

    一般に、1つのトランザクションでデータのコピーのみが変更された場合、他の人はこれらの変更を簡単に確認できません。ただし、分離レベルは異なる場合があります。

    これは、[〜#〜] acid [〜#〜]プロパティであり、単純に白黒でなくても、いくつかのレベルと程度を持つことができます。

    最終的に、[〜#〜] i [〜#〜]solationは、その実装において最も深く、すべての[〜#〜 ] acid [〜#〜]プロパティ。そして、詳細に入るこのプロパティについては、データベースサービスが保証するものについての最初の最も重要なトピックです(のコンテキストでも)- CAP定理ここで、分散データの分離されたビューの一貫性を中心にトレードオフが再び発生します)。

  • [〜#〜] d [〜#〜]耐久性は実際にはむしろ[〜#〜] sla [〜#〜]

    通常、通常のトランザクションロジックの外部で、どのような耐久性(「破損しやすいディスクに書き込まれる」または「プルトニウムを搭載したサーバーのRAM)に冗長に分散される」)がネゴシエートされます。

    実装もかなり簡単で、すべての可能なバッファがフラッシュされた後にのみ、トランザクションが成功したことを確認することになります。

パフォーマンスにとって重要な2つの実装の側面([〜#〜] acid [〜#〜]は明示的に気にしません):

  • 競合の検出

    別のトランザクションで同時に行われた競合する変更を(効率的に)検出する方法が必要です。

    極端な点の1つは、競合の検出を必要としない(同時実行の可能性がない)すべてをロックすることです。

    もう1つの極端な点は、楽観的並行性です(少なくとも部分的に)。次に、同時変更があったかどうかを知る必要があります。これは、実行中のカウンター(バージョン番号)またはデータベース内のさまざまなオブジェクトごとのチェックサムを介して実装できます。次に、これは[〜#〜] i [〜#〜]solationの実装と密接に関連するようになります。

  • ロールバック手順

    これには、変更を元に戻すために、元の値とその変更されたコピー(トランザクションログ)のデータ構造を維持する必要があります。繰り返しますが、これは[〜#〜] i [〜#〜]solationの実装方法に非常に関連しています。

いくつかの追加の短い情報:

  • 簡潔な説明データベースでのトランザクション実装。
  • answerトランザクションで非トランザクションリソースを処理しないようにします。
  • answerアプリケーション内でロールバック可能なメソッドを実装する方法。
4
uvsmtid

一貫性-データはコミットまたはロールバックされ、何かが更新された場合と更新されていない場合の「中間」のケースはありません。

私は、一貫性が何を意味するかについてのアーウィン・スマウトの見解に同意しません-あなたの解釈はお金に近いです。 Ramakrishnan and Gehrke の私の解釈によれば、一貫した状態はシステムの宣言された制約を超えています。

1つの口座から借方に記入し、別の口座に貸方記入することによって2つの口座間で送金する場合、システムはいくつかの状態になる可能性があります。

  1. どちらのアカウントも初期残高を保持しています。
  2. 金額は1つの口座残高から差し引かれますが、他の口座残高には加算されません。
  3. 金額は1つのアカウント残高に追加されますが、他のアカウント残高からは差し引かれません。
  4. どちらのアカウントも最終的な残高を保持しています。

4つの状態すべてにおいて、システムの整合性制約が保持できます。しかし、2番目と3番目はシステムの合理的な見方と一致しません-お金はどこかにあるはずです。したがって、これらは一貫した状態ではありませんが、初期状態と最終状態は一貫しています。

トランザクションは、システムの一貫性を自動的に確立するわけではありません。ユーザーが一貫性を持たせることができます。正しく書かれていないトランザクションには、2番目のアカウントへの入金を忘れるバグがある可能性があります。トランザクションは正常に実行され、整合性制約が保持されます。

しかし、正しく記述された手順は、システムを一貫性のある状態から取得し、一時的に一貫性のないいくつかの変更を行い(たとえば、どちらのアカウントにもお金がない)、システムを一貫性のある状態に戻します。これらのステップをトランザクションに配置することにより、システムが最終的な一貫性のある状態に到達するか(コミットした場合)、または最初の一貫性のある状態に戻る(ロールバックした場合)ことが保証されます。いずれにせよ、一貫性は維持されます。

1
beldaz

「ネストされたトランザクションの評決は何ですか」

評決はありません。ネストされたトランザクションが存在します。 ACIDプロパティが存在します。彼らは共存することを余儀なくされています。絶対的なものはありません。確かにACIDではありません。

0
Erwin Smout