4

Symfony 1.4 / Propel 1.4には既存のプロジェクト(SNSウェブサイト+ android / iPhoneゲーム)があります

DBサーバー(DB1など)に余分な負荷がかかっています。私たちはDB最適化を行っていますが、当面の解決策として、DB2が常にDB1の正確なレプリカである方法でもう1つのDBサーバーを作成することにしました。現在、読み取り操作と書き込み操作の両方に使用されるDB1のみがあります。

次に、すべての読み取り操作をDB2に移動し、書き込み操作(通常はトランザクション内)をDB1でそのまま維持する必要があります。

これらの変更を行うための可能な方法は何ですか(多くのダウンタイムなしで本番サーバー上で)、可能であれば、最小限のコード変更で。

最初のコメントの後に編集

J0kによって提供されたリンクと他のいくつかのリンクに基づいて、ローカル開発環境でフォローしました。

  1. テストsymfony1.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
    

    ここで、データベースは、1つのテストエントリの変更を除いてwzoslv、データベースの正確なレプリカです。wzoテーブルのodd_play行26(PK)の列resultエントリはそれぞれWON1WONです。

  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//期待される出力を修正します

    読み取り接続で、result =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を壊してしまい、Webやログにも何も表示されません。

4

2 に答える 2

4

私は間違いを犯していると確信していますが、Propel / symfonyの公式文書で、そしてここでstackoverflowでさえ提案されたものは、私にはうまくいかないようです。おそらく公式文書は、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;

with(間に1行追加)

// 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に戻しました。)
ファイル:plugins / sfPropelORMPlugin / lib / vendor / propel / runtime / lib/Propel.php
変更601行目

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

to(前に1行追加)

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');
  }
}

私はまだコアファイルを編集することをお勧めしませんが、この解決策は緊急事態のように私たちのために働きました。他の誰かが、必要に応じて、緊急時にそれを使用する可能性があります。まだ完璧な解決策を探しています。

于 2012-11-07T04:02:55.627 に答える
1

ドキュメント(github)によると、slavesプラスconnectionエントリに新しいレベルを追加する必要があります

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
于 2012-11-06T10:19:37.557 に答える