【问题标题】:Long running php process with Doctrine使用 Doctrine 长时间运行的 php 进程
【发布时间】:2017-07-18 15:50:54
【问题描述】:

我创建了一个Symfony 3 命令,预计将运行数天(甚至数周)。它使用Doctrine 2 读取一些初始数据并不时写入执行状态。 SQL 预计需要几毫秒。

我担心的是,如果 MySQL 连接由于不活动而关闭,整个过程最终会崩溃。

问题:Doctrine 是否在 flush 调用之间保持数据库连接打开? 或者,它是否在每次调用 flush 时都重新连接?

【问题讨论】:

  • 不幸的是,批量处理不适用于我的情况。我计划仅在开始和结束过程时更新数据库(这可能需要几天时间)。该进程运行时间很长,但它正在处理来自磁盘/s3 的大量内容。

标签: symfony doctrine-orm


【解决方案1】:

AFAIK Symfony 将在您的应用程序中第一次使用 Doctrine 时打开与数据库的连接,并在发送 HTTP 请求时关闭它(或者如果您明确告诉 Doctrine 关闭它)。连接后,Doctrine 将保持连接处于活动状态,直到您明确关闭它(并且在flush() 之前、期间和之后都将处于活动状态)

在您的情况下,您可能应该在需要时显式地打开和关闭数据库连接。以下代码可以解决您的问题:

// When you need the DB
/**
 * @var \Doctrine\DBAL\Connection $connection
 */
$connection = $this->get('doctrine')->getConnection();
// check if the connection is still active and if not connect to the db
if(!$connection->isConnected()) {
    $connection->connect();
}
// Your code to update the database goes after this.

your code

// Once you're done with the db update - close the connection.
if($connection->isConnected()) {
    $connection->close(); // close the db connection;
}

这将避免数据库连接超时等,但是如果此脚本将按照您的要求运行,您应该非常小心内存泄漏。使用 Symfony 可能不是解决这个问题的最佳方法。

【讨论】:

    【解决方案2】:

    您可以简单地每 1000 秒 ping 一次连接,小于 MySQL 的连接限制。

    最好的办法是运行一个监督进程(例如supervisord),它会在您的应用停止后立即重新启动该进程。然后你可以简单地告诉你的脚本在连接断开之前退出(因为它是一个配置值,例如在 MySQL 中它是 wait_timeout 变量)。监督进程会注意到你的应用程序已经死了,并会重新启动它。

    【讨论】:

    • “你知道 PHP 很糟糕,因为运行时间很长”这在 PHP4 时代可能是真的。我有为 TPS 运行 PHP7.2 的生产代码,并且进程运行了几个月没有任何问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多