A very simple component that allow you to use master/slave splitting database connection.That read operation will route to slave db,write operation will route to master db.Notice:Synchronize bettween master/slave database,you need to config your database and server,this component doesn't complete this job!
Base CDbConnection
Configure it as your system default db connection component.
'components'=>array( 'db'=>array( 'class'=>'DbConnectionMan',//Specify it,instead of CDbConnection,other options is same as CDbConnection 'connectionString' => 'mysql:host=localhost;dbname=test', 'emulatePrepare' => true, 'username' => 'root', 'password' => 'root', 'charset' => 'utf8', 'enableSlave'=>true,//Read write splitting function is swithable.You can specify this value to false to disable it. 'slaves'=>array(//slave connection config is same as CDbConnection array( 'connectionString'=>'mysql:host=slave1;dbname=xxx', 'username'=>'root', 'password'=>'root' ), array( 'connectionString'=>'mysql:host=slave2;dbname=xxx', 'username'=>'demo', 'password'=>'xxx' ), ), ), )
Update 2012-10-08: Support slave db random choices. Fixed:createCommand accept null parameter; Improved:isReadOperation no longer use preg_match (But I can't test new implementation is better than old one which use preg_match)
Total 12 comments
@grigori I have write a simple transation detect:!$this->getCurrentTransaction(). If current query is within a transaction,then always use master db.
Thank you for your attention, this looks better.
Actually, framework should support replication in the inner level. The cases like transactions should be taken into account: within the transaction we can't run SELECTs from the slave. Additionally the sync time should be taken into account and we can't use a slave to SELECT sensitive values like money balances from a slave right after calling a stored procedure.
So the problem is much deeper then just a query analysis.
@grigori I have improved isReadOperation method now.
There is a better solution for replication. The code is abandoned and buggy. That's all I wanted to say. ;)
It's not the end of the world, grigori. Just change
isReadOperation()topublic static function.Any perceived performance drawback from
preg_match()is going to be outweighed heavily by the fact that using this extension you'll have two DB connections open per user, and the fact that it is only used when you're issuing a query, and the query itself will be far heavier than thepreg_match().I.e. New DB connection + query itself (much heavier than)
preg_match():)
A static function should be declared as static.
Pity, but preg_match has a noticable performance drawback and I can't use this.
Response to antonywu (comment #6553), better yet:
This ensures full backwards compatibility.
There are quite a few places where createCommand() is called without a parameter given. For example, if you use CDbHttpSession class, instead of the default CHttpSession, you can run into PHP warnings inside the regenerateID() method.
Thus, the simplest fix is to accept $sql being null and redirect that to the parent::createCommand
thanks very much about this ext, this really helps me a lot~
If needed(I think,it is useful for routing the query to random slave db on each application life cycle,for load balance). declare a init method,add below code:
I think slave connection should always be reused.Because creating connection will spend time,thus there no need for random connection. Could do you describe some cases that need create new slave db connection each read qurey? On the other hand,this component is very simple(only several tens of lines),in fact,in productive environment,I think they will use mysqlproxy to implements read/write splitting. I think this component wasn't really much of use,just an example for the topic that I saw in forum about db read/write splitting ^0^.
Interesting idea... by looking at the code seems that when once a slave is chosen it always returns the same slave... wouldn't be better to choose a different slave for every call?
Or at least have an option/function like randomizeSlave()
Leave a comment
Please login to leave your comment.