Zend Framework multidb 不好用我自己來 Mudb

源由

Zend Framework 的 multidb 有用過因該知道,只是可以把多跟資料庫加入連結 要用時候在拿出其中之一DB來用.
有做過大型連結資料庫的使用著因該深有同感. 你們常做的動作並不是只要拿其中之一的db來做動作.
這樣動作只有在多個不同資料庫才有用而已.(如同時存取mysql mssql ….)

改進功能

  1. 讀寫分離.
  2. 讀取輪詢,分散式負載.
  3. 多重寫入

看到這邊不知道是否有引起你很大興趣呢?

除了讀寫分離,為何還需要讀取輪詢??

一般常用的資料庫,負載平衡主要也是為了分散負載.
不過你是否有跟我一樣困擾:

  • 已經分散了db讀取,卻需要每台server去分配db作為讀取.
  • 每台server都要不同的設定檔或環境,增加mis維護成本時間(煩不煩阿).
  • 某台slave db掛點,mis還須翻找server對應的db 表作為故障排除.當下還的傷透腦筋不知派哪個db給server用

你的福音來了!!使用他每台db使用固定對應表.

此套件運作模式分為Mw & RW 兩種.

Rw模式

可以設定多個matser和多個slave.
在使用下列取的資料的db function時視為 讀取動作

public function fetchAll($sql, $bind = array(), $fetchMode = null){}
public function fetchRow($sql, $bind = array(), $fetchMode = null){}
public function fetchAssoc($sql, $bind = array()){}
public function fetchCol($sql, $bind = array()){}
public function fetchPairs($sql, $bind = array()){}
public function fetchOne($sql, $bind = array()){}

在使用下列取的資料的db function時視為 寫入動作

public function insert($table, array $bind)
public function update($table, array $bind, $where = '')
public function delete($table, $where = '')

看範例說明比較快:
檔案application.ini

; multirwdb Databse setting
autoloadernamespaces[] = "Mudb"
pluginPaths.Mudb_Application_Resource = "Mudb/Application/Resource"
resources.multirwdb.model = "Rw"
resources.multirwdb.master[] = "db1"
resources.multirwdb.master[] = "db5"
resources.multirwdb.slave[] = "db2"
resources.multirwdb.slave[] = "db3"
resources.multirwdb.slave[] = "db4"
resources.multirwdb.db.db1.adapter = "pdo_mysql"
resources.multirwdb.db.db1.host     = "localhost"
resources.multirwdb.db.db1.username = "wacow"
resources.multirwdb.db.db1.password = "123456"
resources.multirwdb.db.db1.dbname   = "wacow"
resources.multirwdb.db.db1.charset  = "UTF8"
resources.multirwdb.db.db1.profiler.enabled = true
resources.multirwdb.db.db1.profiler.class = "Zend_Db_Profiler_Firebug"
 
resources.multirwdb.db.db2.adapter = "pdo_mysql"
resources.multirwdb.db.db2.host     = "localhost"
resources.multirwdb.db.db2.username = "wacow"
resources.multirwdb.db.db2.password = "123456"
resources.multirwdb.db.db2.dbname   = "wacow"
resources.multirwdb.db.db2.charset  = "UTF8"
resources.multirwdb.db.db2.profiler.enabled = true
resources.multirwdb.db.db2.profiler.class = "Zend_Db_Profiler_Firebug"
resources.multirwdb.db.db2.default = true
 
resources.multirwdb.db.db3.adapter = "pdo_mysql"
resources.multirwdb.db.db3.host     = "localhost"
resources.multirwdb.db.db3.username = "wacow"
resources.multirwdb.db.db3.password = "123456"
resources.multirwdb.db.db3.dbname   = "wacow"
resources.multirwdb.db.db3.charset  = "UTF8"
resources.multirwdb.db.db3.profiler.enabled = true
resources.multirwdb.db.db3.profiler.class = "Zend_Db_Profiler_Firebug"
resources.multirwdb.db.db3.default = true
 
resources.multirwdb.db.db4.adapter = "pdo_mysql"
resources.multirwdb.db.db4.host     = "localhost"
resources.multirwdb.db.db4.username = "wacow"
resources.multirwdb.db.db4.password = "123456"
resources.multirwdb.db.db4.dbname   = "wacow"
resources.multirwdb.db.db4.charset  = "UTF8"
resources.multirwdb.db.db4.profiler.enabled = true
resources.multirwdb.db.db4.profiler.class = "Zend_Db_Profiler_Firebug"
resources.multirwdb.db.db4.default = true
 
resources.multirwdb.db.db5.adapter = "pdo_mysql"
resources.multirwdb.db.db5.host     = "localhost"
resources.multirwdb.db.db5.username = "wacow"
resources.multirwdb.db.db5.password = "123456"
resources.multirwdb.db.db5.dbname   = "wacow"
resources.multirwdb.db.db5.charset  = "UTF8"
resources.multirwdb.db.db5.profiler.enabled = true
resources.multirwdb.db.db5.profiler.class = "Zend_Db_Profiler_Firebug"
resources.multirwdb.db.db5.default = true

檔案Bootstrap.php

<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
	protected $_defaultDb = null;
	protected $_CacheDB = null;
	protected $_View = null;
	protected $_Customer = null;
	protected function _initDatabase() {
		if ($this->_defaultDb === null) {
			if ($this->hasPluginResource('multirwdb')) {
				$this->bootstrap('multirwdb');
				$resource = $this->getPluginResource('multirwdb');
				$this->_defaultDb = $resource->getDefaultDb();
			}elseif($this->hasPluginResource('db')){
				$this->bootstrap('db');
				$this->_defaultDb = $this->getPluginResource('db')->getDbAdapter();
			}
		}
		Zend_Registry::set('db',$this->_defaultDb);
	}
     protected function _initZFDebug() {
    if ($this->_defaultDb === null) {
			$this->_initDatabase();
    }
		$options = array(
	    	'plugins' => array(
				'Html',
				'Variables',
				'Memory',
				'Time',
				'Database' => ($this->hasPluginResource('multirwdb')) ? array('adapter' => MuDB_Db::getAllDb()) : array('adapter' => array('default' => $this->_defaultDb)),
				'File' => array('base_path' => realpath(APPLICATION_PATH . '/../')),
				'Registry',
				'Exception',
	 	));
    $debug = new ZFDebug_Controller_Plugin_Debug($options);
		$this->bootstrap('frontController');
		$frontController = $this->getResource('frontController');
		$frontController->registerPlugin($debug);
 
	}

檔案IndexController.php

<?php
class IndexController extends Zend_Controller_Action
{
    public function init()
    {
        $this->db=Zend_Registry::get('db');
    }
 
    public function indexAction()
    {
		$select_test = $this->db->select()->from('system_permissions', '*')->limit(100);
		$result = $this->db->fetchAll($select_test);
		$result = $this->db->fetchAll($select_test);
		$result = $this->db->fetchAll($select_test);
		$result = $this->db->fetchAll($select_test);
		$data= array('test' => rand(5, 15));
		$this->db->insert('test', $data);
    }
}

執行畫面解說:
在IndexController.php indexAction()下我們只是如同往常對單一的db做讀取動做.
總共做了4次,卻在不同db下查詢完成.
卻可以看到執行畫面下,自動輪詢查詢取的資料.
你是否可以發現程式設計師不用傷透腦筋去更改程式碼即可使用此套件即可完成!!
而寫入動作 $this->db->insert(‘test’, $data);
卻是對全部的MASTER做一併寫入更改!!

Mw模式

Mw模式基本上是Rw延伸
設定檔只存取master部分設定!!!
如範例檔案application.ini
只有db1 db5被引用
並將model改為Mw resources.multirwdb.model = “Mw"
而Mw模式下對db做讀取動做會做輪詢.(每個master都會輪詢等同Rw的slave)
寫入動作則一樣,全部寫入.

注意事項

不再列表的圖取寫入動作則做為對db直接的使用.
Rw模式會限制每個Slave db必須為相同的adapter,此處設限為了避免不小心混用db而渾然不知.
因為很多程式設計師select用法會而不同的資料庫而使用特殊語法.

寫入的特殊應用

而不管為Rw 或MW模式 對於寫入動作則不設限.
此方式可以實現有趣的功能 同時對不同的db來源(如同時對mssql 與mysql做同步更新 不過前提是兩邊資料表必須詳同),資料同步寫入變更!!!

總結

此套件花了近一個月修改,其中的經驗與處理模式不知是否讓你產生感慨~~
這些經驗都是爆肝來的,如有取用或發佈請保留引用來源.(檔案內並未有版權註解請隨意使用)
到這邊你以為沒了嗎???
其實還有西可以實現,如本來要加入的讀取權重(但是我不能再爆肝了 交由你吧QQ)
為何需要讀取權重??
很多系統會有開發報表等等做大量的資料處理(例如報表)
如果此時有權重分配即可像此套件的使用方式一樣不用額外定義,只需對大量的讀取另做讀取做權重區分!!

感謝收看 再會byby~~

附件檔案:Mudb.tar

One thought on “Zend Framework multidb 不好用我自己來 Mudb

  1. Pingback: [Web] 連結分享 - 傑夫碎碎唸-有線電視、漫畫、PHP、Pushmail、Blackberry

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *