Lösungen für Probleme, die auftreten, wenn PHP die Multiprozesssimulation gleichzeitiger Transaktionen implementiert

不言
Freigeben: 2023-04-04 14:16:01
nach vorne
3450 Leute haben es durchsucht

Der Inhalt dieses Artikels befasst sich mit der Lösung von Problemen, die auftreten, wenn PHP die Multiprozesssimulation gleichzeitiger Transaktionen implementiert. Ich hoffe, dass er für Sie hilfreich ist.

Tabelle

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);
Nach dem Login kopieren

PHP-Code

// 进程数量
$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;
    }
}
Nach dem Login kopieren

Erwartetes Ergebnis

Das Zählfeld wird voraussichtlich um mehr als 100 sinken und zu einer negativen Zahl werden! Das heißt, mehr reduzieren!

Tatsächliche Ergebnisse

Bei 200 Parallelität sind die Ergebnisse nach mehrmaliger Ausführung wie folgt:

1. count = 65
2. count = 75
3. count = 55
4. count = 84
...
Nach dem Login kopieren

Es ist weit von den Erwartungen entfernt Ergebnis! Warum passiert das?

Erklärung

Lassen Sie uns zunächst die aktuelle Programmausführungsumgebung und die Parallelitätsszenarien klar verstehen. Was ist Parallelität? Die nahezu gleichzeitige Ausführung wird als Parallelität bezeichnet. Die konkrete Erklärung lautet wie folgt:

进程        过程            获取    更新
1-40        同时创建并运行  100     99
41-80       同时创建并运行  99      98
81 - 100    同时创建并运行  98      97
Nach dem Login kopieren

Um die erste Zeile oben zu erklären, wird der 1-40-Unterprozess fast gleichzeitig erstellt und läuft fast gleichzeitig:

进程 1 获取 count = 100,更新 99
进程 2 获取 count = 100,更新 99
...
进程 40 获取 count = 100,更新 99
Nach dem Login kopieren

Tatsächlich funktionieren diese Prozesse alle nicht wie erwartet: Prozess 1 erhält count=100 und aktualisiert 99; Prozess 2 erhält das aktualisierte Ergebnis von Prozess 1 count=99 und erhält 98; das aktualisierte Ergebnis von Prozess 98. Das Ergebnis ist count=1, update 0
, und das Phänomen ist, dass es abnimmt! !

Fazit

In dem mit dem oben genannten Ansatz implementierten Programm ist der Bestand immer >= 0.

Frage

Wie entwerfe ich ein Programm, um ein Szenario mit Überbeständen zu simulieren?

Verwenden Sie weiterhin den obigen Code und ändern Sie den folgenden Code:

if ($count > 0) {
    $count--;
    $pdo->query('update test set `count` = ' . $count . ' where id = 2');
}
Nach dem Login kopieren

wie folgt:

if ($count > 0) {
    $pdo->query('update test set `count` = `count` - 1 where id = 2');
}
Nach dem Login kopieren

Das Ergebnis wird ein Überbestand sein! !

Bestand 100, Parallelität 200, endgültiger Bestand reduziert auf -63. Warum passiert das? Im Folgenden wird der spezifische Prozess zum Ausführen des Programms beschrieben

进程 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)
Nach dem Login kopieren

Es erscheint jetzt verwirrend, wird aber tatsächlich durch die folgende Aussage verursacht:

$pdo->query('update test set `count` = `count` - 1 where id = 2');
Nach dem Login kopieren

Hier finden Sie eine detaillierte Erklärung 进程 1,简称 a;进程 2,简称 b Ihre Besonderheiten Ausführungsreihenfolge:

1. a Abfrage des Inventars 100
b Abfrage des Inventars 100
a Aktualisieren Sie das Inventar auf 99 (100 - 1), dies sollte in Sekunden verstanden werden
4. b Der aktualisierte Bestand beträgt 98 (99 - 1)
– b erhält den aktualisierten Bestand von a, wenn der Aktualisierungsvorgang ausgeführt wird!
– Warum passiert das? Denn die Update-Anweisung lautet „update test set count = count – 1 where id = 2“

Das obige ist der detaillierte Inhalt vonLösungen für Probleme, die auftreten, wenn PHP die Multiprozesssimulation gleichzeitiger Transaktionen implementiert. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:segmentfault.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage