PHP が同時トランザクションのマルチプロセス シミュレーションを実装するときに発生する問題の解決策

不言
リリース: 2023-04-04 14:16:01
転載
3430 人が閲覧しました

この記事の内容は、php で同時トランザクションのマルチプロセスシミュレーションを実装する際に発生する問題の解決策について書いたもので、一定の参考値がありますので、困っている方は参考にしていただければ幸いです。

テーブル

drop table if exists `test`;
create table if not exists `test` (
    id int not null auto_increment , 
    count int default 0 , 
    primary key `id` (`id`)
) engine=innodb character set utf8mb4 collate = utf8mb4_bin comment '测试表';

insert into test (`count`) values (100);
ログイン後にコピー

phpコード

// 进程数量
$pro_count = 100;
$pids = [];
for ($i = 0; $i < $pro_count; ++$i)
{
    $pid = pcntl_fork();
    if ($pid < 0) {
        // 主进程
        throw new Exception(&#39;创建子进程失败: &#39; . $i);
    } else if ($pid > 0) {
        // 主进程
        $pids[] = $pid;
    } else {
        // 子进程
        try {
            $pdo = new PDO(...);
            $pdo->beginTransaction();
            $stmt = $pdo->query('select `count` from test');
            $count = $stmt->fetch(PDO::FETCH_ASSOC)['count'];
            $count = intval($count);
            if ($count > 0) {
                $count--;
                $pdo->query('update test set `count` = ' . $count . ' where id = 2');
            }
            $pdo->commit();
        } catch(Exception $e) {
            $pdo->rollBack();   
            throw $e;
        }
        // 退出子进程
        exit;
    }
}
ログイン後にコピー

望ましい結果

カウント フィールドが 100 以上減少し、負の数になることが予想されます。つまり、もっと減らす!

実際の結果

同時実行数 200 の場合、複数回実行した後の結果は次のとおりです。

1. count = 65
2. count = 75
3. count = 55
4. count = 84
...
ログイン後にコピー

予想とはかけ離れています。結果!なぜこのようなことが起こるのでしょうか?

説明

まず、現在のプログラム実行環境と同時実行シナリオを明確に理解します。同時実行性とは何ですか? ほぼ同時に実行されることを同時実行性といいます。具体的な説明は次のとおりです。

进程        过程            获取    更新
1-40        同时创建并运行  100     99
41-80       同时创建并运行  99      98
81 - 100    同时创建并运行  98      97
ログイン後にコピー

上の最初の行を説明すると、サブプロセス 1 ~ 40 がほぼ同時に作成され、ほぼ同時に実行されます。

进程 1 获取 count = 100,更新 99
进程 2 获取 count = 100,更新 99
...
进程 40 获取 count = 100,更新 99
ログイン後にコピー

つまり、実際には、これらのプロセスはすべて同じ操作を実行しましたが、期待どおりではありませんでした: プロセス 1 はカウント = 100 を取得、更新 99; プロセス 2 はプロセス 1 の更新結果を取得、カウント = 99、更新 98; ...; 処理99 処理98の更新結果を取得、count=1、更新0
、結果として減少するという現象が発生! !

結論

上記のアプローチを使用して実装されたプログラムでは、在庫は常に 0 以上になります。

質問

在庫過剰シナリオをシミュレートするプログラムを設計するにはどうすればよいですか?

引き続き上記のコードを使用し、次のコードを変更します:

if ($count > 0) {
    $count--;
    $pdo->query('update test set `count` = ' . $count . ' where id = 2');
}
ログイン後にコピー

を次のように変更します:

if ($count > 0) {
    $pdo->query('update test set `count` = `count` - 1 where id = 2');
}
ログイン後にコピー

結果は在庫過剰になります。 !

在庫 100、同時実行性 200、最終在庫は -63 に減少しました。なぜそのような状況が起こるのでしょうか?以下に、プログラム動作の具体的なプロセスを説明します。

进程 1 获取库存 100,更新 99
进程 2 获取库存 100,更新 98(99 - 1)
进程 3 获取库存 100,更新 97(98 - 1)
.... 
进程 168 获取库存 1 ,更新 0(1-1)
进程 169 获取库存 1 ,更新 -1(0 - 1)
进程 170 获取库存 1 ,更新 -2(-1 - 1)
....
进程 200 获取库存 1,更新 -63(-62 - 1)
ログイン後にコピー

非常にわかりにくいように思えますが、実際には次のステートメントによって引き起こされます。

$pdo->query('update test set `count` = `count` - 1 where id = 2');
ログイン後にコピー

詳細な説明は次のとおりです。プロセス 1、 a と呼ばれる; プロセス 2、b と呼ばれる 特定の実行シーケンス:

1. a インベントリ 100
2 をクエリします。 b インベントリ 100
3 をクエリします。 a を更新します。インベントリを 99 (100 - 1) にすると、これは数秒で理解できるはずです
4. b インベントリを 98 (99 - 1)
に更新します - b 更新操作を実行すると、取得されるのは更新されたインベントリですああ! ### - なぜこうなった? update ステートメントは「update test set count = count - 1 where id = 2」であるため、

以上がPHP が同時トランザクションのマルチプロセス シミュレーションを実装するときに発生する問題の解決策の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:segmentfault.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!