我们在 Symfony 1.4/Propel 1.4 中有一个现有项目(SNS 网站+android/Iphone 游戏)

我们在 DB 服务器(比如 DB1)上遇到了额外的负载。我们正在做数据库优化,但作为直接的解决方案,我们决定再创建一个数据库服务器,就像 DB2 一直是 DB1 的精确副本一样。目前我们只有 DB1,用于读写操作。

现在我们需要将所有读操作移到 DB2 并保持 DB1 上的写操作(通常在事务中)像现在一样。

进行这些更改的可能方法是什么(在没有太多停机时间的生产服务器上),如果可能,代码更改最少。

在第一条评论后编辑

基于 J0k 给出的链接和其他一些链接,我在本地开发环境中做了以下工作。

  • 创建了一个测试 symfony 1.4 项目
  • 更新 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 条目分别是 WON1WON
  • 运行 symfony 任务
    php symfony propel:build-schema
    php symfony propel:build-model
    php symfony cc
    
  • 创建了一个模块并添加了以下代码:
    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,输出是,


  • 我想在创建读/写连接时传递 OddPlayPeer::DATABASE_NAME 是问题所在,但在线示例中是如何建议的。有人可以建议我在哪里犯错吗?

    编辑:输入更多

    我更新了 lib\vendor\symfony\lib\plugins\sfPropelPlugin\lib\vendor\propel\Propel.php 中的调试 echo 以检查它是如何返回连接的。发现它在下面输入 if (line 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 是空的?

    我还尝试编辑 old forums 中定义的 sfDatabaseConfigHandler.class.php,但这样做会在某处破坏 symfony 并且没有任何内容显示在网络上,甚至在日志中。

    最佳答案

    我确定我犯了一些错误,但是无论 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(中间加了一行)
    // 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(之前加了一行)
    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');
      }
    }
    

    我仍然不建议编辑核心文件,但该解决方案在紧急情况下对我们有用。如果需要,其他人可以在 紧急情况下使用它 。仍在寻找完美的解决方案。

    关于php - Symfony/Propel 1.4 : Read from one, 写入其他数据库,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13234058/

    10-10 23:38