Symfony2:如何将INSERT DELAYED与doctrine一起使用或创建非阻塞数据库操作?

Bel*_*lum 3 php sql database doctrine symfony

出于性能原因,我想使用mysql的INSERT DELAYED查询来持久保存日志对象.

你有什么想法可以使用学说来执行吗?

Nic*_*ich 5

为什么你可能不应该使用INSERT DELAYED:

从MySQL 5.6.6开始,不推荐使用INSERT DELAYED,并将在以后的版本中删除.请改用INSERT(不带DELAYED).

(官方文件)

symfony2解决方案:

使用symfony2,您可以通过为kernel.terminate事件创建侦听器/订户并在其中执行来执行非阻塞数据库操作.

发送响应会触发此事件.例如,它被生产环境中的monolog使用.

首先创建一个监听器类:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

# 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" ]
Run Code Online (Sandbox Code Playgroud)

最后,您可以从控制器或某个服务内部向记录器添加数据,然后在响应发送以非阻塞方式激活并执行数据库操作.

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

    $this->get('long_operation.logger')->setData($whatever)
}
Run Code Online (Sandbox Code Playgroud)