Zend_Db_Tableを利用して複数DBサーバを参照する
DBサーバの負荷分散のために、select文を発行する先のDBを複数用意して運用することがあると思います。マスター(更新&参照)1台に、スレーブ(参照)1台とか。
今回、マスター1台、スレーブ1台の構成で、selectクエリを振り分けるプログラムを作りました。Zend_Db_TableのfetchRow、fetchAll等が呼ばれる度に、クエリを実行するDBサーバを決定します。
まずは、DB接続先の設定をiniファイルに定義します。
接続先情報は、ダミーです。
1 2 3 4 5 6 7 8 | database.adapter = Pdo_Mysql database.params.host = master.test.com database.params.username = dbuser database.params.password = hogehoge database.params.dbname = master # 参照DBhost database.reference.host = slave1 |
次に、Zend_Db_Table_Abstractと各テーブルクラスの間に入れるクラス。
Zend_Db_Table_Abstractクラスの拡張クラスです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | abstract class My_Db_Table_Abstract extends Zend_Db_Table_Abstract { public function fetchAll($where=null, $order=null, $count=null, $offset=null) { // 2回に1回はmasterに接続 if ((rand() % 2) == 0) { return parent::fetchAll($where, $order, $count, $offset); } // 2回に1回はslaveに接続 $adapter = $this->getAdapter(); $this->_setAdapter($this->getReferenceAdapter()); $rows = parent::fetchAll($where, $order, $count, $offset); $this->_setAdapter($adapter); return $rows; } public function fetchRow($where=null, $order=null) { // 2回に1回はmasterに接続 if ((rand() % 2) == 0) { return parent::fetchRow($where, $order); } // 2回に1回はslaveに接続 $adapter = $this->getAdapter(); $this->_setAdapter($this->getReferenceAdapter()); $row = parent::fetchRow($where, $order); $this->_setAdapter($adapter); return $row; } public function getReferenceAdapter() { if (Zend_Registry::isRegistered('Ref_Db_Adapter')) { return Zend_Registry::get('Ref_Db_Adapter'); } $config = new Zend_Config_Ini('↑で作ったconfigファイル名'); $params = $config->database->params->toArray(); $params['host'] = $config->database->reference->host; $db = Zend_Db::factory($config->database->adapter, $params); $db->setFetchMode(Zend_Db::FETCH_ASSOC); Zend_Registry::set('Ref_Db_Adapter', $db); return $db; } } |
テーブルクラスの定義は以下のように
1 2 3 4 5 | class Users extends My_Db_Table_Abstract { protected $_name = 'users'; protected $_primary = 'user_id'; } |
これで、fetchRow、fetchAllを使う際は、masterとslaveにクエリが分散されます