トランザクションを使用していないので、いいえ、1 つのスクリプト内のすべてのクエリが終了するのを待たないため、クエリが重複する可能性があります。
これを教える並行プログラミングと呼ばれる研究分野全体があります。
データベースでは、トランザクション、分離レベル、およびデータ ロックが重要です。
典型的な (単純な) 競合状態:
$visits = $pdo->query('SELECT visits FROM articles WHERE id = 44')->fetch()[0]['visits'];
/*
* do some time-consuming thing here
*
*/
$visits++;
$pdo->exec('UPDATE articles SET visits = '.$visits.' WHERE id = 44');
上記の競合状態は、2 つの PHP プロセスが1 ミリ秒後にデータベースから訪問を読み取ると、簡単に悪化する可能性があります。望ましい効果は、2 回の訪問で値が 2 増加することでした (訪問の最終的な値は8 になるはずでした)。
これに対する解決策は、アトミック操作を使用することです (操作が単純で、1 つのアトミック操作に減らすことができるため)。
UPDATE articles SET visits = visits+1 WHERE id = 44;
アトミック操作は、データベース エンジンによって、他のプロセス/スレッドによって中断されずに実行されることが保証されています。通常、データベースは着信更新をキューに入れ、相互に影響を与えないようにする必要があります。各プロセスは、実行される機会が得られるまで、その前にすべてのプロセスを待機する必要があるため、キューイングは明らかに速度を低下させます。
単純ではない操作では、複数のステートメントが必要です。
SELECT @visits := visits FROM articles WHERE ID = 44;
SET @visits = @visits+1;
UPDATE articles SET visits = @visits WHERE ID = 44;
しかし、データベース レベル 3 でも、個別のアトミック ステートメントがアトミックな結果を生成する保証はありません。それらは他の操作と重複する可能性があります。PHPの例と同じです。
これを解決するには、次のことを行う必要があります。
START TRANSACTION
SELECT @visits := visits FROM articles WHERE ID = 44 FOR UPDATE;
SET @visits = @visits+1;
UPDATE articles SET visits = @visits WHERE ID = 44;
COMMIT;