在symfony4中未使用原始查询的从属服务器

ldfqzlk8  于 2021-06-20  发布在  Mysql
关注(0)|答案(1)|浏览(524)

我使用symfony4与现有的主/从mysql设置接口,并使用原始sql对服务器执行查询。原始sql是目前唯一的选择。
我正在使用show full processlist;在db服务器上监视使用哪个db,我只看到到主服务器的连接。似乎没有奴隶被使用过。
作为参考,我设置了两个dbal连接,默认值不是master/slave,并使用ormMap。第二个是我遇到问题的主/从服务器,这是我对其执行原始sql查询的服务器。
以下是我的信条.yml:

  1. doctrine:
  2. dbal:
  3. default_connection: default
  4. connections:
  5. default:
  6. driver: pdo_mysql
  7. host: "%env(DATABASE_HOST)%"
  8. dbname: "db1"
  9. user: "%env(DATABASE_USER)%"
  10. password: "%env(DATABASE_PASS)%"
  11. charset: UTF8
  12. ds:
  13. driver: pdo_mysql
  14. host: "%env(DS_DATABASE_HOST)%"
  15. dbname: "db2"
  16. user: "%env(DS_DATABASE_USER)%"
  17. password: "%env(DS_DATABASE_PASS)%"
  18. slaves:
  19. slave1:
  20. host: "%env(DS_DATABASE_SLAVE1_HOST)%"
  21. user: "%env(DS_DATABASE_USER)%"
  22. password: "%env(DS_DATABASE_PASS)%"
  23. dbname: "db2"
  24. slave2:
  25. host: "%env(DS_DATABASE_SLAVE2_HOST)%"
  26. user: "%env(DS_DATABASE_USER)%"
  27. password: "%env(DS_DATABASE_PASS)%"
  28. dbname: "db2"
  29. orm:
  30. default_entity_manager: default
  31. entity_managers:
  32. default:
  33. connection: default
  34. mappings:
  35. Main:
  36. is_bundle: false
  37. type: annotation
  38. dir: '%kernel.project_dir%/src/Entity/Main'
  39. prefix: 'App\Entity\Main'
  40. alias: Main
  41. ds:
  42. connection: ds

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

  1. # Entity managers
  2. App\Service\Database\MainEntityManager:
  3. arguments:
  4. $wrapped: '@doctrine.orm.default_entity_manager'
  5. App\Service\Database\DSEntityManager:
  6. arguments:
  7. $wrapped: '@doctrine.orm.ds_entity_manager'

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

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

如果缺少任何有用的配置,请告诉我。
非常感谢你的帮助。

vd2z7a6w

vd2z7a6w1#

谢谢@cerad的提示,这让我找到了正确的方向。因为我不再尝试对未Map到实体的原始查询使用实体管理器,所以我可以直接使用连接。
我创建了一个 Package 类来扩展masterslaveconnection。只要我使用executequery(),它就可以工作。根据文档,必须使用它来查询从机。但是,我的查询需要使用prepare()和query(),这两种方法都强制主连接。
因此,在我的新 Package 类中,我创建了两个新方法prepareslave()和queryslave(),它们的作用与原来的相同;但是,它们执行$this->connect('slave');而不是$this->connect('master');
现在我所有的read查询都命中slave,其他所有查询都命中master。
因此,以下是我对上述配置所做的以下更新:
条令.yml

  1. ds:
  2. driver: pdo_mysql
  3. host: "%env(DS_DATABASE_HOST)%"
  4. dbname: "db2"
  5. user: "%env(DS_DATABASE_USER)%"
  6. password: "%env(DS_DATABASE_PASS)%"
  7. wrapper_class: "%env(DS_DATABASE_PASS)%"
  8. slaves: App\Service\Database\DSWrapper
  9. slave1: ...

服务.yml

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

我的新 Package 类

  1. class DSWrapper extends MasterSlaveConnection
  2. {
  3. public function prepareSlave($statement)
  4. {
  5. $this->connect('slave');
  6. try {
  7. $stmt = new Statement($statement, $this);
  8. } catch (\Exception $ex) {
  9. throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $statement);
  10. }
  11. $stmt->setFetchMode($this->defaultFetchMode);
  12. return $stmt;
  13. }
  14. public function querySlave()
  15. {
  16. $this->connect('slave');
  17. $args = func_get_args();
  18. $logger = $this->getConfiguration()->getSQLLogger();
  19. if ($logger) {
  20. $logger->startQuery($args[0]);
  21. }
  22. $statement = $this->_conn->query(...$args);
  23. if ($logger) {
  24. $logger->stopQuery();
  25. }
  26. return $statement;
  27. }
  28. }

所以现在如果我需要执行一个通常需要使用prepare()和query()的查询,我就使用prepareslave()和queryslave()。

展开查看全部

相关问题