2 人のユーザーが同時に同じクエリをデータベースに送信し、1 人が別のクエリで別の値を返すようにするとどうなりますか?
私は商品が 1 つ残っている店を持っています。2 人以上が商品を購入し、クエリがまったく同時に MySQL サーバーに到着します。私の推測では、キューに入れるだけですが、そうであれば、MySQL は最初に実行するものをどのように選択し、これに影響を与えることができますか?
同じクエリを同時に送信する
クエリは常に並行して実行されるわけではありません
データベースエンジンに依存します。MyISAM では、ほぼすべてのクエリがテーブル レベルのロックを取得します。つまり、クエリはキューとして順次実行されます。他のほとんどのエンジンでは、それらは並行して実行できます。
echo_me 言うnothing happens at the exact same time and a CPU does not do everything at once
それは正確には真実ではありません。複数の CPU と複数のネットワーク インターフェイスを備えたマシンで DBMS を実行することは可能です。2 つのクエリが同時に到着する可能性は非常に低いですが、不可能ではないため、ペアリング/実行遷移が (実行の - 必ずしも同じ軽量プロセスではない) 単一のスレッドとしてのみ実行されることを保証するミューテックスがあります。
同時実行 DML を解決するには 2 つの方法があります。トランザクションを使用する方法 (各ユーザーがデータベースのクローンを効果的に取得する方法) と、クエリが完了すると DBMS が変更を調整しようとする方法のいずれかです。調整が失敗した場合、DBMS はいずれかをロールバックします。クエリを実行し、失敗したと報告します。もう 1 つのアプローチは、行レベルのロックを使用することです。DBMS は、クエリによって更新される行を識別し、更新用に予約されているものとしてマークします (他のユーザーは各行の元のバージョンを読み取ることができますが、データを更新しようとすると、行が再び使用可能になるまでブロックされます)。
問題は、2 つの mysql クライアントがあり、それぞれが在庫が 1 つ残っているという事実を取得していることです。これは、(PHPについて言及しているため)その後の在庫調整とは異なるDBMSセッションで在庫レベルが取得された可能性があるという事実によってさらに複雑になります-HTTPリクエストを超えるトランザクションを持つことはできません。したがって、単一のトランザクション内で DBMS の外部で保持されているファクトを再検証する必要があります。
楽観的ロックは、疑似 - トランザクション制御メカニズムを作成できます - 変更しようとしているレコードに、タイムスタンプとユーザー ID でフラグを立てます (PHP では、PHP セッション ID が適切な選択です) - 変更する場合は、他の何か変更された場合、コードは以前に取得したデータが無効であることを認識しています。ただし、これは他の合併症を引き起こす可能性があります。
これらはユーザーが要求するとすぐに実行されるため、10 人のユーザーが同時にクエリを要求している場合、10 個のクエリがまったく同時に実行されます。
まったく同時に何も起こらず、CPU が一度にすべてを実行するわけではありません。一度に 1 つずつ (コアおよび/またはスレッドごとに) 処理を行います。10 人のユーザーがクエリを実行するページにアクセスしている場合、ユーザーは特定の順序でサーバーに「ヒット」し、その順序で処理されます (ただし、その順序はミリ秒単位の場合があります)。ただし、ページに複数のクエリがある場合、別のユーザーのページのクエリが開始される前に、あるユーザーのページのすべてのクエリが完了するかどうかはわかりません。これにより、同時実行の問題が発生する可能性があります。
編集:
実行SHOW PROCESSLIST
して、強制終了したい接続の ID を見つけます。
SHOW PROCESSLIST
現在実行中のすべてのクエリのリストが表示されます。
ここから。
各クエリは単一のスレッドで実行され、CPU 間で並列化できないため、MySQL は高速な CPU でうまく機能します。
次のようなクエリを検討してください。
UPDATE items SET quantity = quantity - 1 WHERE id = 100
MySQL サーバーが並行して実行するクエリの数に関係なく、そのようなクエリが 2 つ実行され、id
100の行にquantity
1 がある場合、デフォルトで次のようなことが起こります。
items
である行をロックします。id
quantity
を 1 から 0 に変更し、行のロックを解除しますitems
2 番目のクエリは、id
is 100の行をロックします。quantity
を 0 から -1 に変更し、行のロックを解除しますこれは本質的に並行性の問題です。トランザクションを使用して、MySQL で同時実行性を確保する方法があります。これは、eshop で、説明したような競合状態が問題にならないようにすることができることを意味します。MySQL のトランザクションについては、以下のリンクを参照してください。
http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html
http://zetcode.com/databases/mysqltutorial/transactions/
分離レベルに応じて、2 つの同時クエリから異なる結果が返されます。
MySQL のクエリは並行して処理されます。実装の詳細については、こちらをご覧ください。