データベース トランザクションのトピックには、原子性、一貫性、分離性、耐久性を表す頭字語 ACID が伴うことがよくあります。簡単に言うと、トランザクションはデータベース操作が確実に実行され、他の同時接続の影響を受けないことを保証します。
しかし、疑問が生じます。複数の PHP スクリプトは干渉することなくトランザクションを同時に実行できるのでしょうか?これを理解するために、次のシナリオを考えてみましょう。
「employees」という名前のテーブルに、「id」と「salary」という 2 つのフィールドがあるとします。 script1.php と script2.php の 2 つのスクリプトは、次のコードを同時に実行します:
<code class="php">$conn->beginTransaction(); $stmt = $conn->prepare("SELECT * FROM employees WHERE name = ?"); $stmt->execute(['ana']); $row = $stmt->fetch(PDO::FETCH_ASSOC); $salary = $row['salary']; $salary = $salary + 1000; $stmt = $conn->prepare("UPDATE employees SET salary = {$salary} WHERE name = ?"); $stmt->execute(['ana']); $conn->commit();</code>
このシナリオでは、「ana」の給与はいくらになりますか?
答えは以下によって異なります。 MySQL InnoDB テーブル エンジンに設定された分離レベル。 InnoDB は、SQL 標準で指定されている 4 つの分離レベルをサポートします:
デフォルトでは、MySQL は「Read Committed」分離レベルを使用します。このレベルでは、結果は 11000 になります。これは、script1.php と script2.php がどちらかがコミットする前に同じデータを読み取るためです。
「シリアル化可能」分離レベルが使用されている場合、結果は 12000 になります。これは、Serializable によってトランザクションが順番に実行され、他のトランザクションがロックされたデータに干渉するのを防ぐためです。
指定された例では、イベントのシーケンスは次のとおりです。
「Read Committed」分離を使用すると、両方のスクリプトがコミットする前に同じデータを読み取ります。したがって、給与の増加は分離されず 2 回適用され、結果として 2000 の増加となります。
「シリアル化可能」分離では、最初のトランザクション (script1.php) は、「ana」の行をロックします。データを選択します。 script2.php が同じデータを選択しようとすると、最初のトランザクションがコミットされるまで待機します。これにより、データの読み取り中にデータが別のトランザクションによって変更されることがなくなり、給与の増加は 1 回だけ適用され、結果として 1000 の増加となります。
したがって、同時トランザクション間の干渉は、分離レベルと特定の操作シーケンス。トランザクションが同時環境で意図したとおりに動作するようにするには、さまざまな分離レベルの影響を理解することが重要です。
以上がPDO を使用した MySQL トランザクションは干渉することなく同時に実行できますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。