DB Master/Slave issue

在Yii的文档中没有看到关于多DB连接的内容,好不容易在论坛里找到相关的,得到的答案是覆盖Model中的getDbConnection函数,如果这样的话,那么某一个Model岂不是只能对应某一个DB,典型的MySQL Master/Slave应用中,表结构是一样的,是否可以共用Model呢?

比如定义main.php中:

‘master’ => require_once(‘db_master_define.php’),

‘slave’ => require_once(‘db_slave_define.php’),

而某个表的Model是User.php

是否可以在程序中这样调用:

User::model(‘master’)->find();

User::model(‘slave’)->find();

?

看看这个帖子~

http://www.yiiframework.com/forum/index.php?/topic/5712-active-record-save-to-different-server-load-balancefail-over-setup/page__hl__slave__fromsearch__1

这篇帖子里也没有一个定论啊,看起来Yii并没有buildin的多DB连接支持,只能依靠hack,这样代码可读性会降低。

有时未必一定是读用slave,写用master,所以定义自己的AR类,添加onBeforeXXX函数并不能解决所有问题。

我觉得Yii框架还是应该把Model和DBConnection分开,能够传递参数给model

例如以前接触到的框架中,就有Model和Schema之分,

1 Schema类代表一个DB,在其下可以有多个表示Table结构和关系的Class

2 Model调用Schema类,初始化时输入连接参数

这样我可以定义两个Model:DBMaster和DBSlave,它们调用的Schema是相同的,只是连接参数不同

代码里就可以用app()->dbmaster->schema(‘Table’)->find();

app()->dbslave->schema(‘Table’)->find();

一个比较简单的办法是如下定义一个AR基类:




class BaseActiveRecord extends CActiveRecord

{

    public function use($db=null)

    {    

        self::$db=Yii::app()->$db;

        return $this;

    }

}


class Post extends BaseActiveRecord { ... }


Post::model()->findAll(); // use 'db'

Post::model()->use('db2')->findAll(); // use 'db2'

Post::model()->findAll(); // use 'db2'



因为CActiveRecord::$db可以动态修改,你也可以创造出更加优美的一些实现。

got it!帅!

直接在connection维护

这个方法挺透明的;

对模型层等均透明

//日志组件的配置

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’,),

),

);

这样如果DB2不在的话就有问题了

最好还是能支持主从吧