Yiiフレームワークデータベース書き込み分離設計
5961 ワード
Yiiフレームワークはphpで流行しているフレームワークであり,現在多くの開発者が使用している.現在、プロジェクトでmysqlデータベースの主従分離を使用する方法は常態となっている.Yiiではどのように実現しますか?
1、まず自分でデータベースの主従接続クラスを書く必要があります.
2、このクラスをconfigディレクトリのmainファイルに登録します.
3、実現構想はSELECT、SHOWなどの文に出会った時に自動的に従庫に切り替える.
データベース接続クラス:
このクラスをmain.phpに登録します.
プログラム全体の呼び出しといえば、何の違いもありません.
1、まず自分でデータベースの主従接続クラスを書く必要があります.
2、このクラスをconfigディレクトリのmainファイルに登録します.
3、実現構想はSELECT、SHOWなどの文に出会った時に自動的に従庫に切り替える.
データベース接続クラス:
<?php
class DbConnection extends CDbConnection
{
/**
* @var array $slaves.Slave database connection(Read) config array.
* The array value's format is the same as CDbConnection.
* <code>
* 'components'=>array(
* 'db'=>array(
* 'class' => 'DbConnection',
* 'connectionString'=>'mysql://<master>',
* 'slaves'=>array(
* array('connectionString'=>'mysql://<slave01>'),
* array('connectionString'=>'mysql://<slave02>'),
* )
* )
* )
* </code>
*/
public $slaves = array();
/**
* Whether enable the slave database connection.
* Defaut is true.Set this property to false for the purpose of only use the master database.
*
* @var bool $enableSlave
*/
public $enableSlave = true;
/**
* @override
* @var bool $autoConnect Whether connect while init
*/
//public $autoConnect=false;
/**
* @var CDbConnection
*/
private $_slave;
/**
* Creates a CDbCommand object for excuting sql statement.
* It will detect the sql statement's behavior.
* While the sql is a simple read operation.
* It will use a slave database connection to contruct a CDbCommand object.
* Default it use current connection(master database).
*
* @override
* @param string $sql
* @return CDbCommand
*/
public function createCommand($query = null)
{
if ($this->enableSlave && !$this->getCurrentTransaction() && self::isReadOperation($query)) {
return $this->getSlave()->createCommand($query);
} else {
return parent::createCommand($query);
}
}
/**
* Construct a slave connection CDbConnection for read operation.
*
* @return CDbConnection
*/
public function getSlave()
{
if (!isset($this->_slave)) {
foreach ($this->slaves as $slaveConfig) {
if (!isset($slaveConfig['class']))
$slaveConfig['class'] = 'CDbConnection';
try {
if ($slave = Yii::createComponent($slaveConfig)) {
Yii::app()->setComponent('dbslave', $slave);
$this->_slave = $slave;
break;
}
} catch (Exception $e) {
Yii::log('Create slave database connection failed!', 'warn');
continue;
}
}
if (!$this->_slave) {
$this->_slave = clone $this;
$this->_slave->enableSlave = false;
}
}
return $this->_slave;
}
/**
* Detect whether the sql statement is just a simple read operation.
* Read Operation means this sql will not change any thing ang aspect of the database.
* Such as SELECT,DECRIBE,SHOW etc.
* On the other hand:UPDATE,INSERT,DELETE is write operation.
*
* @return bool
*/
public function isReadOperation($sql)
{
return !!preg_match('/^\s*(SELECT|SHOW|DESCRIBE|PRAGMA)/i', $sql);
}
/**
* check Master | slave db is connection
*
* @params bool $isSlave
* @return void
*/
public function ping($isSlave = true)
{
if ($isSlave) {
if ($this->getActive()) {
$connect = $this->getSlave();
try {
$connect->getPdoInstance()->query('SELECT 1');
} catch (PDOException $e) {
$connect->setActive(false);
$connect->setActive(true);
}
}
} else {
if ($this->getActive()) {
try {
$this->getPdoInstance()->query('SELECT 1');
} catch (PDOException $e) {
$this->setActive(false);
$this->setActive(true);
}
}
}
}
}
このクラスをmain.phpに登録します.
'public_db_common' => array(
'class' => 'DbConnection', // DbConnection
'connectionString' => "mysql:host=;dbname=;port=",
'emulatePrepare' => true,
'username' => ,
'password' => ,
'tablePrefix' => 't_',
'charset' => 'utf8',
'enableProfiling' => true, //
'enableParamLogging' => true, //
'slaves' => array(
array(
'connectionString' => "mysql:host=;dbname=;port=",
'emulatePrepare' => true,
'username' => ,
'password' => ,
'charset' => 'UTF8',
'tablePrefix' => 't_',
'enableParamLogging' => YII_DEBUG,
'schemaCacheID' => 'cache',
'schemaCachingDuration' => 0,
)
),
),
プログラム全体の呼び出しといえば、何の違いもありません.