繁体   English   中英

如何在加载 Doctrine 装置时禁用控制台中的查询日志记录?

[英]How to disable query logging in console while load Doctrine fixtures?

我有一个加载大量数据的装置,我一直遇到这个错误:

致命错误:第 65 行的 /var/www/html/platform-cm/vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/DebugStack.php 中允许的内存大小为 2147483648 字节(试图分配 16777224 字节)

[Symfony\\Component\\Debug\\Exception\\OutOfMemoryException] 错误:允许的内存大小为 2147483648 字节已用完(尝试分配 16777224 字节)

经过一番研究,我发现这篇文章中我读到日志记录可能是问题的原因,因为AppKernel实例化时默认设置为 true,然后 SQL 命令在每次迭代时存储在内存中。

AppKernel没有禁用调试的第一次尝试是运行以下命令:

doctrine:fixtures:load --no-debug

但是我没有走运,因为仍然出现同样的错误。

第二次尝试是在config_dev.yml禁用调试,但不建议这样做,因为我正在访问每个日志但也没有工作。

monolog:
    handlers:
        main:
            type:   stream
            path:   "%kernel.logs_dir%/%kernel.environment%.log"
            level:  debug
#        console:
#            type:   console
#            bubble: false
#            verbosity_levels:
#                VERBOSITY_VERBOSE: INFO
#                VERBOSITY_VERY_VERBOSE: DEBUG
#            channels: ["!doctrine"]
#        console_very_verbose:
#            type:   console
#            bubble: false
#            verbosity_levels:
#                VERBOSITY_VERBOSE: NOTICE
#                VERBOSITY_VERY_VERBOSE: NOTICE
#                VERBOSITY_DEBUG: DEBUG
#            channels: ["doctrine"]

所以,这就是我的灯具的样子:

class LoadMsisdn extends AbstractFixture implements OrderedFixtureInterface
{
    public function getOrder()
    {
        return 13;
    }

    public function load(ObjectManager $manager)
    {
        $content = file_get_contents('number.txt');
        $numbers = explode(',', $content);
        shuffle($numbers);

        foreach ($numbers as $key => $number) {
            $msisdn = new Msisdn();
            $msisdn->setMsisdn($number);
            $msisdn->setBlocked((rand(1, 1000) % 10) < 7);
            $msisdn->setOperator($this->getReference('operator-' . rand(45, 47)));

            $this->addReference('msisdn-' . $key, $msisdn);
            $manager->persist($msisdn);
        }

        $manager->flush();
    }
}

如果我需要从EntityManager执行此操作,如何禁用记录器,如同一帖子的答案所示?

$em->getConnection()->getConfiguration()->setSQLLogger(null);

传递给load方法的对象管理器是实体管理器的一个实例( Doctrine\\Common\\Persistence\\ObjectManager只是实体/文档/等管理器实现的接口)。

这意味着您可以使用与您的问题相同的命令来使 SQL 记录器无效,例如..

$manager->getConnection()->getConfiguration()->setSQLLogger(null);

需要注意的一件事是 DBAL 连接的默认日志记录设置是%kernel.debug%这意味着,除非您在配置中覆盖它,否则日志记录应该只发生在dev环境中。 我可以看到您已尝试使用--no-debug选项,但我只能假设,由于在容器编译期间设置了记录器,因此它不会将其取消设置为未重建的容器。


测试用例中的 Symfony 3/4/5 方法

final class SomeTestCase extends KernelTestCase
{
    protected function setUp(): void
    {
        $this->bootKernel('...');

        // @see https://stackoverflow.com/a/35222045/1348344
        // disable Doctrine logs in tests output
        $entityManager = self::$container->get(EntityManagerInterface::class);
        $entityManager->getConfiguration();
        $connection = $entityManager->getConnection();

        /** @var Configuration $configuration */
        $configuration = $connection->getConfiguration();
        $configuration->setSQLLogger(null);
    }
}

我不确定它是否有助于解决内存限制问题,但您也可以尝试通过 YAML 配置更改日志记录(更舒适):


禁用 Doctrine 日志通道

(如您评论的代码)

monolog:
    handlers:
        main:
            type:   stream
            path:   "%kernel.logs_dir%/%kernel.environment%.log"
            level:  debug
            channels: ["!doctrine"]    # "!event", "!php"

设置自定义虚拟记录器

services.yaml为默认的 Doctrine 记录器设置类:

doctrine.dbal.logger:
        class: App\ORM\Doctrine\DBAL\Logging\DummySQLLogger

并在doctrine.yaml启用它:

doctrine:
    dbal:
        driver: 'pdo_mysql'
        logging: true

自定义记录器必须实现接口Doctrine\\DBAL\\Logging\\SQLLogger 具体方法startQuerystopQuery可以留空,跳过日志记录; 或者只是使用error_log代替(就像我的情况一样)。


我不确定这是否会防止内存超出问题。 最终增加PHP_MEMORY_LIMIT (通过环境变量,如果您的环境支持,或通过ini_set() )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM