在yii中实现主从分离功能

在实际工作中,有主从分离,随机读取从服务器等需求。我是这样来解决的。




class YLActiveRecord extends CActiveRecord{

	public $YL_DBType='';

 	/*

 	 * 重写CActiveRecord,中的方法,该方法取得main.php 中定义的数据库连接数组

 	 */

	public function getDbConnection()

    {

	   	$this->YL_DBType;

	    switch ($this->YL_DBType)

		{

			case 'ylslave':

			  $yldb='dbread';

			  break;

			case 'ylmaster':

			  $yldb='db';

			  break;

			default:

			 $yldb='db';

		}

		/*

		 * 测试定义为随机链接

		 */

		$yldb=array('db','dbread');

		$i=rand(0,1);

		

        self::$db=Yii::app()->getComponent($yldb[$i]);

        if(self::$db instanceof CDbConnection)

            return self::$db;

         else

            throw new CDbException(Yii::t('yii','Active Record requires a "db" CDbConnection application component.'));


    }

	protected function beforeSave()

	{

		$this->YL_DBType='ylmaster';

		parent::beforeSave();

	}

	protected function beforeDelete()

	{

		$this->YL_DBType='ylmaster';

		parent::beforeDelete();

	}

	protected function beforeFind()

	{

		$this->YL_DBType='ylslave';

		parent::beforeFind();

	}

}



这里还可以对从服务器做随机选择(出错选择)等,各位如有需要可自行加入。在models继承此类即可。

重写了CActiveRecord中的beforeSave,beforeFind,getDbConnection等方法。经测试yii 1.1.8中可用。

思想不错 不过侵入性太强 强迫大家继承你写的AR了 主从分离在扩展库中已经有人实现了 扩展 CDbConnection 即可 根据createCommand 方法的参数$query 正则查找 是否满足 查询性质 或者如果是更新性质(delete update) 那么使用不同的链接 写用主 读用从库

我现在用的一个connectionMan 但是缺点是不支持query-builder。。。还是希望强弄个官方版。

http://www.yiiframework.com/forum/index.php?/topic/10865-db-read-write-splitting/

//日志组件的配置

return array(

‘class’=>‘CDbConnectionExt’,

‘emulatePrepare’ => true,

‘charset’ => ‘utf8’,

//主数据库配置

‘connectionString’ => ‘mysql:host=localhost;dbname=a;port=3306’,

‘username’ => ‘root’,

‘password’ => ‘11’,

//从数据库配置

‘slaveConfig’=>array(

array(‘connectionString’=>‘mysql:host=localhost;dbname=a;port=3306’,‘username’=>‘root’,‘password’=>‘11’,),

array(‘connectionString’=>‘mysql:host=localhost;dbname=a;port=3306’,‘username’=>‘root’,‘password’=>‘11’,),

array(‘connectionString’=>‘mysql:host=localhost;dbname=a;port=3306’,‘username’=>‘root’,‘password’=>‘11’,),

array(‘connectionString’=>‘mysql:host=localhost;dbname=a;port=3306’,‘username’=>‘root’,‘password’=>‘11’,),

),

);