Symfony/Propel 1.4: чтение из одной, запись в другую БД

У нас есть существующий проект (сайт SNS + игры для Android/Iphone) в Symfony 1.4/ Propel 1.4

Мы испытываем дополнительную нагрузку на сервер БД (скажем, DB1). Мы занимаемся оптимизацией БД, но в качестве немедленного решения мы решили создать еще один сервер БД, чтобы DB2 всегда была точной копией DB1. В настоящее время у нас есть только DB1, используемый для операций чтения и записи.

Теперь нам нужно перенести все операции чтения в DB2 и сохранить операции записи (обычно в транзакциях) в DB1, как сейчас.

Каковы возможные способы внесения этих изменений (на рабочем сервере без больших простоев) и, если возможно, с минимальными изменениями кода.

Изменить после первого комментария

Основываясь на ссылке, предоставленной J0k, и некоторых других ссылках, я сделал следующее в локальной среде разработчика.

  1. Создан тестовый проект Symfony 1.4
  2. Обновлен database.yml следующим образом

    all:
      propel:
        class: sfPropelDatabase
        param:
          classname: PropelPDO
          dsn: 'mysql:host=localhost;dbname=wzo;'
          username: root
          password: mysql
          encoding: utf8
          persistent: true
          pooling: true
        slaves:
          slave1:
            dsn:      'mysql:host=localhost;dbname=wzoslv;'
            username: root
            password: mysql
            encoding: utf8
    

    Где база данных wzoslv точная копия базы данных wzo кроме изменений в одной тестовой записи. На столе odd_play строка 26 (PK) столбец result записи WON1 а также WON соответственно.

  3. запускать задачи Symfony

    php symfony propel:build-schema
    php symfony propel:build-model
    php symfony cc
    
  4. Создал модуль и добавил следующий код:

    class wzoActions extends sfActions
    {
      public function executeIndex(sfWebRequest $request)
      {
        $con_write = Propel::getConnection(OddPlayPeer::DATABASE_NAME, Propel::CONNECTION_WRITE);
        $con_read = Propel::getConnection(OddPlayPeer::DATABASE_NAME, Propel::CONNECTION_READ);
        $oddPlay = OddPlayPeer::retrieveByPK(26,0,$con_write);
        echo "on write connection, result=".$oddPlay->getResult();
        $oddPlayRead = OddPlayPeer::retrieveByPK(26,0,$con_read);
        echo "<br/>on Read connection, result=".$oddPlayRead->getResult();
        exit;
        $this->setLayout('layout');
      }
    }
    

    Бежать http://local.sftest.com/index.php/wzo/index в браузере вывод был,

    при записи соединения, result=WON // Исправить ожидаемый результат

    при подключении для чтения, результат = WON // Неправильно. Это должно быть WON1

Я думаю прохождение OddPlayPeer::DATABASE_NAME Хотя создание соединения для чтения / записи является проблемой, но именно так, как это было предложено в онлайн-примерах. Может кто-нибудь подсказать, где я ошибаюсь?

Изменить: немного больше ввода

Я обновил отладочный эхо в lib\vendor\symfony\lib\plugins\sfPropelPlugin\lib\vendor\propel\Propel.php чтобы проверить, как он возвращает соединение. Обнаружил, что ввод в следующем if (строка 544-549)

$slaveconfigs = isset(self::$configuration['datasources'][$name]['slaves']) ? self::$configuration['datasources'][$name]['slaves'] : null;

if (empty($slaveconfigs)) {
  echo "inelseifif<br/>";// no slaves configured for this datasource
  self::$connectionMap[$name]['slave'] = false;
  return self::getConnection($name, Propel::CONNECTION_WRITE); // Recurse to get the WRITE connection
}

где $slaveconfigs пустые, поэтому возвращаем соединение для записи. Теперь вопрос, почему slaveconfigs пуст?

Я также пытаюсь отредактировать sfDatabaseConfigHandler.class.php, как это было определено на старых форумах, но, делая это, где-то ломаю symfony и ничего не отображается в сети и даже в журналах.

2 ответа

Решение

Я уверен, что делаю какую-то ошибку, но все, что предлагается в официальных документах Propel / symfony и даже здесь, в stackru, кажется, не работает для меня. Вероятно, официальные документы должны лучше заботиться о программистах, которые не имеют большого опыта Symfony.

Хотя мы не предпочитаем редактировать основные файлы каких-либо фреймворков / сторонних библиотек, но это заставляет меня редактировать основные файлы, чтобы сделать рабочее решение для меня. Решение, которое сработало для меня, заключается в следующем:

database.yml Мой файл database.yml выглядит следующим образом:

all:
  propel:
    class: sfPropelDatabase
    param:
      classname: PropelPDO
      dsn: 'mysql:host=localhost;dbname=wzo;'
      username: testuserwzo
      password: 
      encoding: utf8
      persistent: true
      pooling: true

  slave:
    class: sfPropelDatabase
    param:
      classname: PropelPDO
      dsn: 'mysql:host=localhost;dbname=wzoslv;'
      username: testuserwzoslv
      password: 
      encoding: utf8
      persistent: true
      pooling: true

После этого я отредактировал файл Propel.php следующим образом

Для Propel 1.4
Файл: lib/vendor/ symfony / lib / plugins / sfPropelPlugin / lib/vendor/ propel / Propel.php
Смена строки 542-543

// we've already ensured that the configuration exists, in previous if-statement
$slaveconfigs = isset(self::$configuration['datasources'][$name]['slaves']) ? self::$configuration['datasources'][$name]['slaves'] : null;

с (добавлено одна строка между)

// we've already ensured that the configuration exists, in previous if-statement
self::$configuration['datasources'][$name]['slaves'] = isset(self::$configuration['datasources']['slave']) ? self::$configuration['datasources']['slave'] : null;
$slaveconfigs = isset(self::$configuration['datasources'][$name]['slaves']) ? self::$configuration['datasources'][$name]['slaves'] : null;

Затем в том же файле изменили строку 560

$con = Propel::initConnection($conparams, $name);

в

$con = Propel::initConnection($conparams, 'slave'); //I know its bad practive to put hard-coded value but at that moment, I was more interested in working solution without caring about best practices.

Для propel 1.6 (мы обновили propel только для того, чтобы это работало, но позже вернулись к propel 1.4, так как обновление на производстве должно быть хорошо протестировано.)
Файл: плагины /sfPropelORMPlugin/lib/vendor/propel/runtime/lib/Propel.php
Изменена линия 601

$slaveconfigs = isset(self::$configuration['datasources'][$name]['slaves']) ? self::$configuration['datasources'][$name]['slaves'] : null;

в (добавлена ​​одна строка раньше)

self::$configuration['datasources'][$name]['slaves'] = isset(self::$configuration['datasources']['slave']) ? self::$configuration['datasources']['slave'] : null;
$slaveconfigs = isset(self::$configuration['datasources'][$name]['slaves']) ? self::$configuration['datasources'][$name]['slaves'] : null;

Затем в том же файле изменили строку 629

$con = Propel::initConnection($conparams, $name);

в

$con = Propel::initConnection($conparams, 'slave');

Затем следующий тестовый файл дал ожидаемый результат

class kapsActions extends sfActions
{
  public function executeIndex(sfWebRequest $request)
  {
      $con_write = Propel::getConnection(OddPlayPeer::DATABASE_NAME, Propel::CONNECTION_WRITE);
      $con_read = Propel::getConnection(OddPlayPeer::DATABASE_NAME, Propel::CONNECTION_READ);

      $oddPlay = OddPlayPeer::retrieveByPK(28,0,$con_write);
      echo "on write connection, result=".$oddPlay->getResult().$oddPlay->getPlayscore();

      $oddPlayRead = OddPlayPeer::retrieveByPK(27,0,$con_read);
      echo "<br/>on Read connection, result=".$oddPlayRead->getResult().$oddPlayRead->getPlayscore();
      exit;
      //$this->setLayout('layout');
  }
}

Я до сих пор не рекомендую редактировать основные файлы, но это решение работало для нас как в аварийном состоянии. Кто-то другой, при необходимости, может использовать его в аварийном состоянии. Все еще ищем идеальное решение.

Вы должны добавить новый уровень slaves плюс connection запись, согласно документу (на github)

all:
  propel:
    class: sfPropelDatabase
    param:
      classname: PropelPDO
      dsn: 'mysql:host=localhost;dbname=wzo;'
      username: root
      password: mysql
      encoding: utf8
      persistent: true
      pooling: true

      slaves:
        connection:
          slave1:
            dsn:      'mysql:host=localhost;dbname=wzoslv;'
            username: root
            password: mysql
            encoding: utf8
Другие вопросы по тегам