sql >> データベース >  >> RDS >> Mysql

MySQL:トランザクションとテーブルのロック

    テーブルをロックすると、他のDBユーザーがロックした行/テーブルに影響を与えるのを防ぐことができます。ただし、ロック自体は、ロジックが一貫した状態で出力されることを保証するものではありません。

    銀行システムについて考えてみてください。オンラインで請求書を支払う場合、トランザクションの影響を受けるアカウントは少なくとも2つあります。アカウントからお金を受け取ります。そして、送金先の受取人の口座。そして、銀行の口座には、取引で請求されたすべてのサービス料金が喜んで預け入れられます。 (最近誰もが知っているように)銀行が非常に愚かであることを考えると、彼らのシステムが次のように機能するとしましょう:

    $balance = "GET BALANCE FROM your ACCOUNT";
    if ($balance < $amount_being_paid) {
        charge_huge_overdraft_fees();
    }
    $balance = $balance - $amount_being paid;
    UPDATE your ACCOUNT SET BALANCE = $balance;
    
    $balance = "GET BALANCE FROM receiver ACCOUNT"
    charge_insane_transaction_fee();
    $balance = $balance + $amount_being_paid
    UPDATE receiver ACCOUNT SET BALANCE = $balance
    

    現在、ロックやトランザクションがないため、このシステムはさまざまな競合状態に対して脆弱です。その最大のものは、アカウントまたは受信者のアカウントで並行して実行される複数の支払いです。コードで残高が取得され、huge_overdraft_fees()などが実行されている間、他の支払いで同じタイプのコードが並行して実行される可能性があります。彼らはあなたの残高(たとえば$ 100)を取得し、彼らの取引を行い(あなたが支払っている$ 20と、彼らがあなたを台無しにしている$ 30を取り出します)、そして今、両方のコードパスは2つの異なる残高を持っています:$80と70ドル。どちらが最後に終了するかに応じて、最終的には$ 50($ 100-$ 20-$ 30)ではなく、アカウントにこれら2つの残高のいずれかが表示されます。この場合、「あなたに有利な銀行エラー」。

    ここで、ロックを使用するとします。請求書の支払い($ 20)が最初にパイプに当たるので、それが勝ち、アカウントレコードをロックします。これで、排他的に使用できるようになり、残高から$ 20を差し引いて、新しい残高を安心して書き戻すことができます...そして、アカウントは予想どおり$80になります。しかし...ええと...受信者のアカウントを更新しようとすると、ロックされ、コードで許可されているよりも長くロックされ、トランザクションがタイムアウトになります...私たちは愚かな銀行を扱っているので、適切なエラーが発生する代わりに処理中、コードはexit()をプルするだけです 、そしてあなたの$20は一吹きの電子に消えます。今、あなたは$ 20を出している、そしてあなたはまだ$ 20を受信者に借りている、そしてあなたの電話は取り戻される。

    だから...トランザクションを入力します。取引を開始し、アカウントから$ 20を引き落とし、受信者に$ 20を入金しようとすると、何かが再び爆発します。ただし、今回はexit()の代わりに 、コードはrollbackを実行できます 、そしてうんざりして、あなたの$20は魔法のようにあなたのアカウントに戻されます。

    結局、それはこれに要約されます:

    ロックは、他の誰かがあなたが扱っているデータベースレコードに干渉するのを防ぎます。トランザクションは、「後の」エラーが「前の」ことを妨げるのを防ぎます。どちらも単独では、物事が最終的にうまくいくことを保証することはできません。しかし、一緒に、彼らはそうします。

    明日のレッスン:デッドロックの喜び。



    1. MySQLデータベース開発のためのGearHost入門

    2. テーブルが変化しているため、トリガー/関数に表示されない場合があります(平均グレードが2.5を下回るのを防ぐ)

    3. SQLServerデータベースをあるインスタンスから別のインスタンスにコピーする方法

    4. SQLServerでSELECTからUPDATEを使用する方法