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


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

我有一个加载大量数据的灯具,但每次都遇到此错误:

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

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

经过一番研究,我发现了这篇文章,我读到日志记录可能是问题的原因,因为默认情况下AppKernel debug设置为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 配置(更舒适地(更改日志记录:

<小时 />

禁用原则日志通道

(如您注释的代码(

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

设置自定义虚拟记录器

services.yaml中,设置默认原则记录器的类:

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(如果您的环境支持,则通过 env 变量,或通过 ini_set() (。并注意使用正确的单位符号(兆字节M,千兆字节G(,我经常把它写错为MB.