我们在 Symfony 1.4/Propel 1.4 中有一个现有项目(SNS 网站+android/Iphone 游戏)
我们在数据库服务器(比如 DB1)上遇到了额外的负载。我们正在进行数据库优化,但作为直接解决方案,我们决定再创建一个数据库服务器,因为 DB2 始终是 DB1 的精确副本。目前我们只有 DB1,用于读写操作。
现在我们需要将所有读取操作移至 DB2,并保持 DB1 上的写入操作(通常在事务中)保持原样。
进行这些更改的可能方法是什么(在生产服务器上没有太多停机时间),如果可能,代码更改最少。
第一条评论后编辑
根据 J0k 给出的链接和其他一些链接,我在本地开发环境中完成了以下操作。
更新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。/p>
运行 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,输出为,
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/
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
我需要一些关于TDD概念的帮助。假设我有以下代码defexecute(command)casecommandwhen"c"create_new_characterwhen"i"display_inventoryendenddefcreate_new_character#dostufftocreatenewcharacterenddefdisplay_inventory#dostufftodisplayinventoryend现在我不确定要为什么编写单元测试。如果我为execute方法编写单元测试,那不是几乎涵盖了我对create_new_character和display_invent
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01 客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02 数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit