Symfony2:如何使用INSERT delay with doctrine或创建一个非阻塞的数据库操作?

时间:2022-09-15 20:12:17

For performance reasons I would like to persist a log object using mysql's INSERT DELAYED query.

出于性能原因,我希望使用mysql的INSERT delay查询来持久化日志对象。

Do you have any ideas how that could be performed using doctrine?

你知道怎么用教义来执行吗?

1 个解决方案

#1


5  

Why you probably shouldn't use INSERT DELAYED:

As of MySQL 5.6.6, INSERT DELAYED is deprecated, and will be removed in a future release. Use INSERT (without DELAYED) instead.

从MySQL 5.6.6开始,插入延迟被弃用,并将在以后的版本中删除。使用插入(不延迟)代替。

(official documentation)

(官方文档)

The symfony2 solution:

With symfony2 you can perform a non-blocking database-operation by creating a listener/subscriber for the kernel.terminate event and executing it in there.

使用symfony2,您可以通过为内核创建侦听器/订阅器来执行非阻塞数据库操作。终止事件并在其中执行它。

This event is fired after the response has been sent. It's being used by monolog in the production environment for example.

此事件在发送响应之后被触发。例如,它在生产环境中被独白使用。

Create a listener class first:

首先创建一个监听器类:

namespace Acme\Your;

use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\HttpKernel\Event\KernelEvent;

class LongOperationLogger
{
    protected $om;
    protected $data;

    public function __construct(ObjectManager $om)
    {
        $this->om = $om;
    }

    public function setData($data)
    {
        $this->data = $data;
    }

    public function onKernelTerminate(KernelEvent $event)
    {
        // don't do anything if there is not data
        if ( null !== $this->data ) {
            return;
        }

        $logEntry = new LogEntry('I will not block the response.', $this->data);

        $this->om->persist($logEntry);
        $this->om->flush();
    }
}

Then define it as a service and inject your object-manager:

然后将其定义为服务并注入对象管理器:

# app/config/config.yml

services:
    long_operation.logger:
        class: Acme\Your\LongOperationLogger
        tags:
            - { name: kernel.event_listener, event: kernel.terminate }
        arguments: [ "@doctrine.orm.entity_manager" ]

Finally, you can add data to the logger from inside a controller or some service which in turn activates and executes the database-operation in a non-blocking way after the response has been sent.

最后,您可以从控制器或某些服务中向日志记录器中添加数据,这些服务在响应发送之后以非阻塞的方式激活并执行数据库操作。

public function someAction()
{
    // some condition
    // if (...) {
    //     ...
    // }

    $this->get('long_operation.logger')->setData($whatever)
}

#1


5  

Why you probably shouldn't use INSERT DELAYED:

As of MySQL 5.6.6, INSERT DELAYED is deprecated, and will be removed in a future release. Use INSERT (without DELAYED) instead.

从MySQL 5.6.6开始,插入延迟被弃用,并将在以后的版本中删除。使用插入(不延迟)代替。

(official documentation)

(官方文档)

The symfony2 solution:

With symfony2 you can perform a non-blocking database-operation by creating a listener/subscriber for the kernel.terminate event and executing it in there.

使用symfony2,您可以通过为内核创建侦听器/订阅器来执行非阻塞数据库操作。终止事件并在其中执行它。

This event is fired after the response has been sent. It's being used by monolog in the production environment for example.

此事件在发送响应之后被触发。例如,它在生产环境中被独白使用。

Create a listener class first:

首先创建一个监听器类:

namespace Acme\Your;

use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\HttpKernel\Event\KernelEvent;

class LongOperationLogger
{
    protected $om;
    protected $data;

    public function __construct(ObjectManager $om)
    {
        $this->om = $om;
    }

    public function setData($data)
    {
        $this->data = $data;
    }

    public function onKernelTerminate(KernelEvent $event)
    {
        // don't do anything if there is not data
        if ( null !== $this->data ) {
            return;
        }

        $logEntry = new LogEntry('I will not block the response.', $this->data);

        $this->om->persist($logEntry);
        $this->om->flush();
    }
}

Then define it as a service and inject your object-manager:

然后将其定义为服务并注入对象管理器:

# app/config/config.yml

services:
    long_operation.logger:
        class: Acme\Your\LongOperationLogger
        tags:
            - { name: kernel.event_listener, event: kernel.terminate }
        arguments: [ "@doctrine.orm.entity_manager" ]

Finally, you can add data to the logger from inside a controller or some service which in turn activates and executes the database-operation in a non-blocking way after the response has been sent.

最后,您可以从控制器或某些服务中向日志记录器中添加数据,这些服务在响应发送之后以非阻塞的方式激活并执行数据库操作。

public function someAction()
{
    // some condition
    // if (...) {
    //     ...
    // }

    $this->get('long_operation.logger')->setData($whatever)
}