Zend Framework DB Load Balancing (Master/Slave Database)

網路上找來找去……
沒看到有人寫相關的解法….
加上不想用mysql-proxy來解這部份…

所以打算從code 的部份下手
看到最後只能動Zend Framework 的code 了(還沒想到可以不動ZF 的code 而做到DB LB的方法)

我是先從function save 下手去找..

Zend/Table/Row/Abstract.php:    public function save()

[sourcecode language=’php’]
public function save()
{
/**
* If the _cleanData array is empty,
* this is an INSERT of a new row.
* Otherwise it is an UPDATE.
*/
if (empty($this->_cleanData)) {
return $this->_doInsert();
} else {
return $this->_doUpdate();
}
}
[/sourcecode]

ZF會自已做update or insert 的區分

再看
[sourcecode language=’php’]
/**
* @return mixed The primary key value(s), as an associative array if the
* key is compound, or a scalar if the key is single-column.
*/
protected function _doInsert()
{
/**
* A read-only row cannot be saved.
*/
if ($this->_readOnly === true) {
require_once ‘Zend/Db/Table/Row/Exception.php’;
throw new Zend_Db_Table_Row_Exception(‘This row has been marked read-only’);
}

/**
* Run pre-INSERT logic
*/
$this->_insert();

/**
* Execute the INSERT (this may throw an exception)
*/
$data = array_intersect_key($this->_data, $this->_modifiedFields);
$primaryKey = $this->_getTable()->insert($data);

/**
* Normalize the result to an array indexed by primary key column(s).
* The table insert() method may return a scalar.
*/
if (is_array($primaryKey)) {
$newPrimaryKey = $primaryKey;
} else {
$newPrimaryKey = array(current((array) $this->_primary) => $primaryKey);
}

/**
* Save the new primary key value in _data. The primary key may have
* been generated by a sequence or auto-increment mechanism, and this
* merge should be done before the _postInsert() method is run, so the
* new values are available for logging, etc.
*/
$this->_data = array_merge($this->_data, $newPrimaryKey);

/**
* Run post-INSERT logic
*/
$this->_postInsert();

/**
* Update the _cleanData to reflect that the data has been inserted.
*/
$this->_refresh();

return $primaryKey;
}
[/sourcecode]

$primaryKey = $this->_getTable()->insert($data);

程式在
Zend/Adapter/Abstract.php
這邊有
function update()
function insert()

來看
[sourcecode language=’php’]
public function insert($table, array $bind)
{
// extract and quote col names from the array keys
$cols = array();
$vals = array();
foreach ($bind as $col => $val) {
$cols[] = $this->quoteIdentifier($col, true);
if ($val instanceof Zend_Db_Expr) {
$vals[] = $val->__toString();
unset($bind[$col]);
} else {
$vals[] = ‘?’;
}
}

// build the statement
$sql = “INSERT INTO ”
. $this->quoteIdentifier($table, true)
. ‘ (‘ . implode(‘, ‘, $cols) . ‘) ‘
. ‘VALUES (‘ . implode(‘, ‘, $vals) . ‘)’;

// execute the statement and return the number of affected rows
$stmt = $this->query($sql, array_values($bind));
$result = $stmt->rowCount();
return $result;
}
[/sourcecode]

不管insert or update
都是透過query 這個method 去執行sql

所以就在這邊下手吧

[sourcecode language=’php’]
public function query($sql, $bind = array())
{
// connect to the database if needed
if ($sql instanceof Zend_Db_Select) {
if (preg_match(‘/UPDATE|INSERT|REPLACE/i’,$sql->__toString())) {
$this->closeConnection();
$this->_config[‘dbname’] = ‘DB_WRITE’;
}
} else {
if (preg_match(‘/UPDATE|INSERT|REPLACE/i’,$sql)) {
$this->closeConnection();
$this->_config[‘dbname’] = ‘DB_WRITE’;
}
}
$this->_connect();

// is the $sql a Zend_Db_Select object?
if ($sql instanceof Zend_Db_Select) {
$sql = $sql->assemble();
}

// make sure $bind to an array;
// don’t use (array) typecasting because
// because $bind may be a Zend_Db_Expr object
if (!is_array($bind)) {
$bind = array($bind);
}

// prepare and execute the statement with profiling
$stmt = $this->prepare($sql);
$stmt->execute($bind);
// return the results embedded in the prepared statement object
$stmt->setFetchMode($this->_fetchMode);

if ($sql instanceof Zend_Db_Select) {
if (preg_match(‘/UPDATE|INSERT|REPLACE/i’,$sql->__toString())) {
$this->closeConnection();
$this->_config[‘dbname’] = ‘DB_READ’;
$this->_connect();
}
} else {
if (preg_match(‘/UPDATE|INSERT|REPLACE/i’,$sql)) {
$this->closeConnection();
$this->_config[‘dbname’] = ‘DB_READ’;
$this->_connect();
}
}
return $stmt;
}
[/sourcecode]

就是很簡單的去parse $sql 是否有UPDATE,INSERT,REPLACE 之類的寫入語法
若有的話就改config

基本上就是這樣…

如果有人有更好的做法…
拜拖 指教一下小第………..
實在是不想弄到ZF 裡面的code 來達到DB LB的功能..

發佈留言

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料