You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony中Doctrine主从连接调试:如何查看查询执行的主/从库

如何在Symfony+Doctrine的主从配置中查看查询使用的是主库还是从库

要解决这个主从查询追踪的问题,最可靠的方式是自定义Doctrine的SQL日志记录器,把每条查询对应的连接类型(主库/从库)直接追加到日志输出里。下面是具体的实现步骤:

方法一:自定义Doctrine SQL Logger

这个方法能让你全局控制日志内容,每条查询前都会明确标注是主库还是从库,方便长期调试。

  1. 创建自定义日志类
    在你的Symfony项目中,新建src/Logger/CustomDoctrineLogger.php文件,实现Doctrine的SQLLogger接口:
<?php

namespace App\Logger;

use Doctrine\DBAL\Logging\SQLLogger;
use Doctrine\DBAL\Connection;
use Psr\Log\LoggerInterface;

class CustomDoctrineLogger implements SQLLogger
{
    private $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    public function startQuery($sql, array $params = null, array $types = null)
    {
        // 获取当前活跃的数据库连接
        $connection = Connection::getCurrentConnection();
        
        // 利用Doctrine主从连接自带的方法判断是否为从库
        $connectionType = $connection->isConnectedToSlave() ? 'SLAVE' : 'MASTER';

        // 输出带连接类型标记的日志
        $this->logger->debug(sprintf('[%s] %s', $connectionType, $sql), [
            'params' => $params ?? [],
            'types' => $types ?? [],
        ]);
    }

    public function stopQuery()
    {
        // 接口要求必须实现,无需额外操作
    }
}
  1. 注册服务并配置Doctrine使用它
    在config/services.yaml中注册这个自定义日志服务:
services:
    App\Logger\CustomDoctrineLogger:
        arguments: ['@logger'] # 依赖Symfony默认的日志服务

然后在config/packages/doctrine.yaml里,给你的主从连接配置指定这个SQL日志器:

doctrine:
    dbal:
        default_connection: default
        connections:
            default:
                url: '%env(DATABASE_URL)%' # 主库连接地址
                slave:
                    - url: '%env(DATABASE_SLAVE_URL)%' # 从库连接地址
                sql_logger: '@App\Logger\CustomDoctrineLogger' # 启用自定义日志器
  1. 查看日志
    重启应用后,执行tail -f app/logs/dev/dev-2018-05-15.log(如果是Symfony 4+版本,日志路径为var/log/dev.log),就能看到每条查询前都标注了[MASTER]或[SLAVE],轻松区分查询走的是哪个库。

方法二:临时验证方案(快速调试)

如果只是临时需要验证某段代码的查询连接,可以在代码中手动输出连接信息:

$connection = $entityManager->getConnection();
dump($connection->isConnectedToSlave() ? '当前使用从库' : '当前使用主库');

不过这个方法只能针对特定代码块,无法全局追踪所有查询。

额外调试提示

  • Doctrine默认会自动将读操作路由到从库,写操作路由到主库。如果遇到副本延迟导致的旧数据问题,可以强制读主库:
    $query = $entityManager->createQuery('SELECT u FROM App\Entity\User u');
    $query->setHint(\Doctrine\ORM\Query::HINT_FORCE_PARTITION, 'master');
    $users = $query->getResult();
    
  • 确保dev环境的日志级别设置为DEBUG,这样所有Doctrine查询都会被记录到日志中。

内容的提问来源于stack exchange,提问作者Bouffe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 10:02:50