ホームページ  >  記事  >  データベース  >  データベースにおけるトランザクションと同時実行の問題の例

データベースにおけるトランザクションと同時実行の問題の例

零下一度
零下一度オリジナル
2017-07-03 16:10:391351ブラウズ

データベースのトランザクションと同時実行の問題についてのディスカッション

はじめに

最近、同僚が注文作成ロジックを担当するコードを作成しましたが、コードレビュー中に同時実行の問題がある可能性があることが判明しました。私の同僚はこれに同意しませんでした。彼のロジックは ストアド プロシージャ で記述されているため、問題はないはずだと考えていました。

コードのロジックはおそらく (擬似コード) です:

begin transaction

if 查询到客户存在进行中的订单
 rollback transaction

if 查询到设备存在进行中的订单
 rollback transaction

插入订单

commit transaction

以下は、このロジックの分析と、このトランザクションに並行性の問題が発生する理由です。

取引概要

まず、2 つの質問をし、次に質問に基づいて取引に関連する知識ポイントを話し合い、最後にこれら 2 つの質問を解決し、前の質問に答えます。

最初の質問、トランザクションは同時実行できますか?

2 番目の質問、データベースはトランザクションをどのように分離しますか?

トランザクションのパフォーマンス特性

データベース内でのトランザクションの実行には、重要なリソースの処理方法、ロックおよびロック解除の方法など、多くの側面が関係します。ただし、トランザクションがどのように実行されるかに関係なく、次の特性を保証する必要があります:

  • 原子性

  • 一貫性

  • 分離

  • 原子性: すべての操作は論理単位ですどちらかです送信が成功したか失敗したか。

  • 整合性: 正当なデータのみがデータベースに書き込まれます。それ以外の場合、トランザクションは元の状態にロールバックされます。

    分離: トランザクションの正確性と整合性を破壊することなく、同時に処理を続行できます。データ;

    永続性: トランザクションの終了後、送信された結果は固定化されて保存されます。

    さまざまなデータベース ロック

    共有ロック
  1. 共有ロックは、非排他的なビジネスに使用され、複数のトランザクションがロックされたリソースを同時に読み取ることができますが、リソースを更新することはできません。

ロックタイミング:select文実行時にデフォルトで追加されます

  • ロック解除タイミング:読み込み完了後にデフォルトで解除されます
  • 他のロックとの互換性:共有ロックが設定されている場合共有ロックと排他ロックの追加が許可されます
  • 同時実行パフォーマンス: 優れた同時実行パフォーマンスがあります
  • 排他ロック
    1. 排他ロック、排他ロックとも呼ばれます。名前が示すように、排他ロックによってロックされたリソースは、他のトランザクションによる操作の実行を許可しません。

    ロックのタイミング: 挿入、更新、

    削除の実行時にデフォルトで追加されます
  • ロック解除のタイミング: トランザクション終了後にのみ解放可能
  • 互換性: データに他のロックがある場合、排他ロックは追加できません。同様に、排他ロックが存在する間は他のロックを追加できません
  • 同時実行パフォーマンス: 他のトランザクションは実行する前に前のトランザクションの終了を待つ必要があります。同時に実行され、シリアルにのみ更新できます
    1. 読み取りフェーズ中の共有ロックの使用によって引き起こされるデッドロックを防ぐために、更新の初期フェーズで必要なリソースをロックするために使用されます。

    ロックのタイミング: 更新を実行するとき、更新ロックを使用して関連リソースをロックします

  • ロック解除のタイミング: 読み取り後、更新操作を実行するときに、更新ロックが排他ロックにアップグレードされます
  • 互換性: 更新ロックと共有ロック互換性、つまり、更新ロックと共有ロックは同時に存在できますが、存在できる更新ロックは 1 つだけです
  • 同時実行パフォーマンス: 更新の初期段階の読み取りフェーズでは、他のトランザクションがリソースを読み取ることができます。制限された同時実行を許可します。後で、リソースを排他的に同時実行できないようにすることができます。
  • トランザクション分離レベル

  • 一般的なトランザクション分離レベルは 4 つあり、SQL Server には追加の拡張レベルがありますが、ここでは詳しく紹介しません。

    Serializable
    1. は反復可能な読み取りのように機能します。ただし、影響を受けるデータをロックするだけでなく、範囲もロックします。これにより、クエリの対象範囲に新しいデータが挿入され、ファントム読み取りにつながる可能性のある状況が防止されます。

    Repeatable Read (反復可能な読み取り)
    1. コミットされた読み取りレベルと同様にデータを読み取りますが、トランザクションの終了まで共有ロックが保持されます。

    Read Commit
    1. コミットされたデータのみを読み取り、他のトランザクションが排他ロックを解放するのを待ちます。データ読み取りの共有ロックは、読み取り操作が完了するとすぐに解放されます。 Read Committed は、SQL Server のデフォルトの分離レベルです。

    Read Uncommited
    1. は、データの読み取り時にロックをチェックしたり使用したりしません。したがって、この分離レベルではコミットされていないデータを読み取ることが可能です。
    前の質問に答えてください

    最初の質問、トランザクションは同時実行できますか?

    答えは「はい」です。パフォーマンスを向上させるために、データベースでは複数の

    トランザクション操作

    を同時に実行できます。

    Use ストアド プロシージャが開始されるか、コードを使用して開始されるか、通常の SQL ステートメントを使用して開始されるかに違いはありません。 2 番目の質問は、データベースはトランザクションをどのように分離するのでしょうか?

    この質問に答えるには、まずデータベースのロック メカニズムとデータベース トランザクション分離レベルを理解する必要があります。データベースのロックは、共有ロック、排他ロック、更新ロックの 3 つのタイプに分類できます。さまざまなレベルのロックを使用し、さまざまなロック スコープと連携して、さまざまなトランザクション分離レベルを実現し、これに基づいてトランザクションを同時または連続的に実行します。

    3 番目の質問は、この記事の冒頭のトランザクションに同時実行性の問題があるのはなぜですか?

    select はトランザクションの開始時に実行され、select は共有ロックを使用するため、同時トランザクションが select を同時に実行し、それらがすべて同時に正当な操作であると認識してキューに入れられる可能性があります。後続のトランザクションを実行するまで。その結果、実際には、重複したデータを挿入する可能性があります。たとえば、残っている製品は 1 つだけですが、2 つの販売注文が作成されます。

    同時実行の問題を防ぐ方法

    1. トランザクション内

    前述によると、挿入、更新、または削除を使用すると、デフォルトのトランザクションレベルで人為的にトランザクションのシリアル化を引き起こす可能性があるため、内部で最初から更新を使用できますトランザクション 同じ種類のトランザクションがシリアル化されるように公開データを更新し、その後のトランザクション内容を実行するかどうかを決定する判定文を追加します。これは、すべての操作が合理的かつ合法的に実行されることを保証するのに十分です。唯一の欠点は、パフォーマンスの問題が発生する可能性があることです。

    1. トランザクションの外

    現在、分散システムがますます増えていますが、再分散システムには、redis や Zookeeper などの共有リソースも含まれています。redis や Zookeeper を使用して分散ロック (これはこのカテゴリは他のブログ投稿に属しているため、ここでは展開されません)。トランザクションの外部でロックを使用して同じタイプのトランザクションをシリアル化し、トランザクションの内部チェック メカニズムと連携するだけで、トランザクションの同時実行性の問題を確実に解決できます。

    参考資料

  • トランザクション同時実行の問題と処理

  • データベーストランザクションの4大特徴とトランザクションの分離レベル

  • データベーストランザクションと同時実行

  • SQL Serverトランザクションの分離レベル


  • 以上がデータベースにおけるトランザクションと同時実行の問題の例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。