mysql - Symfony 4 中未使用原始查询的从站

标签 mysql symfony doctrine slave rawsql

我正在使用 Symfony 4 与现有的主/从 MySQL 设置进行交互,并使用原始 sql 对服务器执行查询。原始 SQL 是目前唯一的选择。

我正在使用显示完整进程列表;在数据库服务器上监视使用哪个数据库,并且我只看到与主服务器的连接。似乎没有任何奴隶被使用过。

作为引用,我有两个 dbal 连接设置,默认不是主/从,并使用 orm 映射。第二个是我遇到问题的主/从服务器,这是我正在执行原始 sql 查询的服务器。

下面是我的 Doctrine .yml:

doctrine:
    dbal:
        default_connection: default
        connections:
            default:
                driver:   pdo_mysql
                host:     "%env(DATABASE_HOST)%"
                dbname:   "db1"
                user:     "%env(DATABASE_USER)%"
                password: "%env(DATABASE_PASS)%"
                charset:  UTF8
            ds:
                driver:   pdo_mysql
                host:     "%env(DS_DATABASE_HOST)%"
                dbname:   "db2"
                user:     "%env(DS_DATABASE_USER)%"
                password: "%env(DS_DATABASE_PASS)%"
                slaves:
                    slave1:
                        host:     "%env(DS_DATABASE_SLAVE1_HOST)%"
                        user:     "%env(DS_DATABASE_USER)%"
                        password: "%env(DS_DATABASE_PASS)%"
                        dbname:   "db2"
                    slave2:
                        host:     "%env(DS_DATABASE_SLAVE2_HOST)%"
                        user:     "%env(DS_DATABASE_USER)%"
                        password: "%env(DS_DATABASE_PASS)%"
                        dbname:   "db2"

orm:
    default_entity_manager: default
    entity_managers:
        default:
            connection: default
            mappings:
                Main:
                    is_bundle: false
                    type: annotation
                    dir: '%kernel.project_dir%/src/Entity/Main'
                    prefix: 'App\Entity\Main'
                    alias: Main
        ds:
            connection: ds

我在 services.yml 中配置了实体管理器,如下所示:

# Entity managers
App\Service\Database\MainEntityManager:
    arguments:
        $wrapped: '@doctrine.orm.default_entity_manager'
App\Service\Database\DSEntityManager:
    arguments:
        $wrapped: '@doctrine.orm.ds_entity_manager'

实体管理器(在本例中为 DSEntityManager)被注入(inject)到类的构造函数中,然后按如下方式执行查询:

    $result = $this->em->getConnection()->prepare($sql);
    $result->execute($args);

如果我缺少任何有用的配置,请告诉我。

非常感谢您的帮助。

最佳答案

感谢@Cerad 的提示,这让我找到了正确的方向。由于我不再尝试使用实体管理器来处理未映射到实体的原始查询,因此我可以直接使用连接。

我创建了一个扩展 MasterSlaveConnection 的包装类。只要我使用executeQuery(),这个方法就有效。根据文档,必须使用它来查询从站。然而,我的查询需要使用prepare()和query(),它们都会强制主连接。

因此,在我的新包装类中,我创建了两个新方法,prepareSlave() 和 querySlave(),它们的作用与原始方法相同;然而,他们这样做 $this->connect('slave');而不是 $this->connect('master');

现在我所有的读取查询都会命中从属,而其他所有查询都会命中主控。

因此,为了实现此目的,我对上述配置进行了以下更新:

Doctrine .yml

        ds:
            driver:   pdo_mysql
            host:     "%env(DS_DATABASE_HOST)%"
            dbname:   "db2"
            user:     "%env(DS_DATABASE_USER)%"
            password: "%env(DS_DATABASE_PASS)%"
            wrapper_class: "%env(DS_DATABASE_PASS)%"
            slaves: App\Service\Database\DSWrapper
                slave1: ...

服务.yml

# DBAL connections
App\Service\Database\DSWrapper: '@doctrine.dbal.ds_connection'

我的新包装类

class DSWrapper extends MasterSlaveConnection
{
public function prepareSlave($statement)
{
    $this->connect('slave');

    try {
        $stmt = new Statement($statement, $this);
    } catch (\Exception $ex) {
        throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $statement);
    }

    $stmt->setFetchMode($this->defaultFetchMode);

    return $stmt;
}

public function querySlave()
{
    $this->connect('slave');

    $args = func_get_args();

    $logger = $this->getConfiguration()->getSQLLogger();
    if ($logger) {
        $logger->startQuery($args[0]);
    }

    $statement = $this->_conn->query(...$args);

    if ($logger) {
        $logger->stopQuery();
    }

    return $statement;
}
}

所以现在如果我需要执行通常需要使用prepare()和query()的查询,我会使用prepareSlave()和querySlave()。

关于mysql - Symfony 4 中未使用原始查询的从站,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50954000/

相关文章:

Python 脚本无法识别 Mysql 查询

php - 如何使用唯一的随机序列号更新我的 MySQL 表列?

php - 我可以在 PHP 中混合使用 MySQL API 吗?

php - 如何更新 Doctrine 中的字段以将其设置为空

php - Doctrine/Symfony 乱序生成迁移

symfony - 如何从 JMS 序列化器获取始终数组?

PostgreSQL 咨询锁不适用于 Doctrine 的 DBAL

mysql - 在一个 Mysql 中合并 2 个查询

mongodb - Doctrine2 Mongodb 添加更多 $or 运算符

php - 如何在 session 期间配置 Symfony2 粘性语言环境