mysqli::begin\u事务在php fork中失败

6jygbczu  于 2021-06-20  发布在  Mysql
关注(0)|答案(0)|浏览(156)

我想知道mysqli事务在php fork(使用pcntl\u fork())中不能正常工作是否有任何原因?
我有一个在php fork中调用另一个的脚本,在第二个脚本中,我以事务模式进行了一些数据库操作。我很乐意在这些操作中插入一个错误的查询,它应该停止脚本并回滚db操作。事实上,脚本按预期停止,但数据库中存在数据库更改(没有调用commit)。
我尝试在fork外部手动启动第二个脚本,其行为与预期一致,因此问题一定来自fork。
你知道吗?
(如果需要的话,我可以发布我的代码,但是它有点繁杂而且很难阅读……)
编辑:伪代码示例:
分叉脚本:

$pid = pcntl_fork();
if ($pid < 0) {
    errorHandling;
} else if ($pid == 0) {// In the son
    sleep(1); // Waiting the father register the son's pid
    $this->pid = getmypid();
    $this->worker = $workerManager->fetchBy(array('pid' => $this->pid)); // Get the worker object from db. It contains info about the fork in order to cleanup when it finished the work.
    $this->launchScript($this->worker->getAction()); // This function just call session_write_close in the son and includes the second script
} else { // In the father
    $worker = new Worker($pid); // Create the db object I talked about in the son
    $workerManager->create($worker); // Put it in db
    Ajax::Response(OK, "Launched", $pid); // Answer the request and exits the process (without waiting the son, this is done by a cron elsewere)
}

第二个脚本伪代码:

$db = new DB_Cognix(); // Just a mysqli encapsulation
$db->enableTransaction(); // Calls $mysqli->begin_transaction()
try {
/*

**Some DB operations (Inserts, Updates and Selects)
* /

    $db->query("FOOBARBAZ"); // A bad query, the db encapsulation will throw an Exception.
} catch (Throwable $e) {
    $db->rollback(); // calls mysqli::rollback()
    $worker->setErrorMessage($e->getMessage());
    $workerManager->update($worker); // This uses another db object and is not concerned by the transaction
    exit;
}
$db->commit(); // Calls mysqli::commit();
exit("OK");

第二个脚本在退出时停止;并且worker在db中更新,但是db操作仍然完成。当直接从我的浏览器调用第二个脚本时,效果很好,回滚就完成了。
编辑2:我尝试了一个非常简单的代码,看看是否fork是原因,它就像一个魅力,所以我不认为问题来自于fork。。。

<?php
        $pid = pcntl_fork();
        if ($pid < 0) {
            exit("ERROR: Fork failed!");
        } else if ($pid == 0) {
            session_write_close();
            fastcgi_finish_request();
            $db = new DB_Cognix("", true);
            $db->enableTransaction();
            for ($i = 0; $i < 10; ++$i) {
                $db->query("INSERT INTO Tests (id1, id2) VALUES ($i, $i)");
            }
            $db->rollback();
            exit();
        } else {
            echo "Child launched";
            session_write_close();
            fastcgi_finish_request();
            $status = 0;
            pcntl_waitpid($pid, $status);
            exit;
        }
        ?>

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题