gpt4 book ai didi

php - Symfony/Propel 1.4 : Read from one, 写入其他数据库

转载 作者:可可西里 更新时间:2023-10-31 22:56:50 25 4
gpt4 key购买 nike

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

我们在数据库服务器(比如 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 条目分别是 WON1WON/p>

  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,输出为,

    on write connection, result=WON //Correct expected output

    on Read connection, result=WON //Not correct. That should be 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 是空的?

我还尝试按照 old forums 中的定义编辑 sfDatabaseConfigHandler.class.php但是这样做会在某个地方破坏 symfony,并且不会在网络上什至日志中显示任何内容。

最佳答案

我确定我犯了一些错误,但无论是 Propel/symfony 的官方文档甚至是 stackoverflow 上的建议,似乎都不适合我。可能官方文档应该更好地照顾那些没有很多 symfony 经验的程序员。

虽然我们不喜欢编辑任何框架/第三方库的核心文件,但这迫使我编辑核心文件来为我制定一个可行的解决方案。对我有用的解决方案如下:

数据库.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;

到(前加一行)

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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com