Heim  >  Artikel  >  Backend-Entwicklung  >  Lösungen für Probleme, die auftreten, wenn PHP die Multiprozesssimulation gleichzeitiger Transaktionen implementiert

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

不言
不言nach vorne
2018-12-07 17:47:303387Durchsuche

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);

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;
    }
}

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
...

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

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

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');
}

wie folgt:

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

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)

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

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

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!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen