이 기사의 예에서는 Yii가 여러 데이터베이스에서 마스터-슬레이브 읽기 및 쓰기 분리를 구현하는 방법을 설명합니다. 참고할 수 있도록 모든 사람과 공유하세요. 구체적인 분석은 다음과 같습니다.
Yii 프레임워크 데이터베이스 다중 데이터베이스, 마스터-슬레이브, 읽기-쓰기 분리 구현, 기능 설명:
1. 마스터-슬레이브 데이터베이스에서 읽기와 쓰기의 분리를 실현합니다. 마스터 데이터베이스: 쓰기. 슬레이브 데이터베이스(여러 개일 수 있음): 읽기
2. 마스터 데이터베이스를 연결할 수 없는 경우 슬레이브 데이터베이스에 쓰기 가능 여부를 설정할 수 있습니다
3. 모든 슬레이브 데이터베이스를 연결할 수 없는 경우 마스터 데이터베이스를 읽을 수 있는지 여부를 설정할 수 있습니다
4. 데이터베이스 연결이 실패하면 N초 내에 다시 연결되지 않도록 설정할 수 있습니다.
yii 확장을 사용하여 구현한 코드는 다음과 같습니다.
/**
* 기본 데이터베이스는 데이터베이스에서 쓰기 및 읽기(여러 개일 수 있음)
* 마스터-슬레이브 데이터베이스에서 읽기와 쓰기의 분리를 실현합니다. 마스터 서버는 연결할 수 없으며 슬레이브 서버는 쓰기 기능을 전환할 수 있습니다
* 슬레이브 서버는 접속이 불가능합니다. 마스터 서버는 읽기 기능을 전환할 수 있습니다
* 작성자: LMT
**/
클래스 DbConnectionMan은 CDbConnection {
을 확장합니다.
공개 $timeout = 10; //연결 시간 초과
Public $markDeadSeconds = 600; //데이터베이스 연결이 실패하면 600초 이내에 더 이상 연결이 이루어지지 않습니다.
//캐시를 캐시 전역 태그로 사용
공개 $cacheID = '캐시'
/**
* @var array $slaves.Slave 데이터베이스 연결(읽기) 구성 배열입니다.
* 配置符合 CDbConnection.
* @예제
* '구성요소'=>배열(
* 'db'=>배열(
* 'connectionString'=>'mysql://',
* '노예'=>배열(
* array('connectionString'=>'mysql://'),
* array('connectionString'=>'mysql://'),
* )
* )
* )
**/
공개 $slaves = 배열()
/**
* *
* 슬레이브 데이터베이스 상태가 false인 경우 마스터 데이터베이스만 사용됩니다
* @var bool $enableSlave
**/
공개 $enableSlave = true
/**
* @varslavesWrite 비상 마스터 데이터베이스를 연결할 수 없습니다. 슬레이브 서버를 전환하십시오(읽기 및 쓰기).
*/
공개 $slavesWrite = 거짓
/**
* @var masterRead 긴급 상황 시 슬레이브 마스터 데이터베이스를 연결할 수 없는 경우 슬레이브 서버로 전환(읽기 및 쓰기)하세요.
*/
공개 $masterRead = 거짓
/**
* @var _slave
*/
개인 $_슬레이브
/**
* @var _disableWrite 슬레이브(읽기 전용)
*/
비공개 $_disableWrite = true
/**
* *
* createCommand 메소드를 다시 작성하세요. 1. 슬레이브 라이브러리 열기 2. 슬레이브 라이브러리에서 존재 3. 현재 트랜잭션에 있지 않음 4. 라이브러리에서 데이터 읽기
* @param 문자열 $sql
* @return CDbCommand
**/
공용 함수 createCommand($sql = null) {
if ($this->enableSlave && !emptyempty($this->slaves) && is_string($sql) && !$this->getCurrentTransaction() && self::isReadOperation($sql) && ($slave = $ this->getSlave())
) {
return $slave->createCommand($sql)
} else {
If (!$this->masterRead) {
If ($this->_disableWrite && !self::isReadOperation($sql)) {
throw new CDbException("마스터 DB 서버는 현재 사용할 수 없습니다. 슬레이브 서버에서 쓰기 작업을 허용하지 않습니다!")
~
}
return parent::createCommand($sql)
}
}
/**
* 서버에서 연결 리소스 가져오기
* @return CDbConnection
**/
공개 함수 getSlave() {
if (!isset($this->_slave)) {
shuffle($this->슬레이브);
foreach ($this->$slaveConfig로서의 슬레이브) {
if ($this->_isDeadServer($slaveConfig['connectionString'])) {
계속하다;
}
if (!isset($slaveConfig['class']))
$slaveConfig['class'] = 'CDbConnection';
$slaveConfig['autoConnect'] = 거짓;
{
을 시도해 보세요.
if ($slave = Yii::createComponent($slaveConfig)) {
Yii::app()->setComponent('dbslave', $slave);
$slave->setAttribute(PDO::ATTR_TIMEOUT, $this->timeout);
$slave->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
$slave->setActive(true);
$this->_slave = $슬레이브;
부서지다;
}
} 잡기(예외 $e) {
$this->_markDeadServer($slaveConfig['connectionString']);
Yii::log("슬레이브 데이터베이스 연결에 실패했습니다!ntConnection string:{$slaveConfig['connectionString']}", 'warning');
계속하다;
}
}
if (!isset($this->_slave)) {
$this->_slave = null;
$this->enableSlave = false;
}
}
$this->_slave를 반환합니다.
}
공개 함수 setActive($value) {
if ($value != $this->getActive()) {
if ($value) {
{
을 시도해 보세요.
if ($this->_isDeadServer($this->connectionString)) {
throw new CDbException('마스터 DB 서버가 이미 종료되었습니다!');
}
//PDO::ATTR_TIMEOUT은 pdo 인스턴스 생성 전에 설정되어야 합니다
$this->setAttribute(PDO::ATTR_TIMEOUT, $this->timeout);
$this->open();
} 잡기(예외 $e) {
$this->_markDeadServer($this->connectionString);
$slave = $this->getSlave();
Yii::log($e->getMessage(), CLogger::LEVEL_ERROR, 'Exception.CDbException');
if ($slave) {
$this->connectionString = $slave->connectionString;
$this->사용자 이름 = $slave->사용자 이름;
$this->password = $slave->password;
if ($this->slavesWrite) {
$this->_disableWrite = 거짓;
}
$this->open();
} else { //슬레이브도 사용할 수 없습니다
if ($this->masterRead) {
$this->connectionString = $this->connectionString;
$this->사용자 이름 = $this->사용자 이름;
$this->password = $this->password;
$this->open();
} 다른 {
throw new CDbException(Yii::t('yii', 'CDbConnection이 DB 연결을 열지 못했습니다.'), (int) $e->getCode(), $e->errorInfo);
}
}
}
} 다른 {
$this->close();
}
}
}
/**
* 읽기 작업 SQL 문 감지
* *
* 키워드: SELECT,DECRIBE,SHOW...
* 쓰기 작업: UPDATE, INSERT, DELETE...
**/
공개 정적 함수 isReadOperation($sql) {
$sql = substr(ltrim($sql), 0, 10);
$sql = str_ireplace(array('SELECT', 'SHOW', 'DESCRIBE', 'PRAGMA'), '^O^', $sql); //^O^, 마법의 미소
return strpos($sql, '^O^') === 0;
}
/**
* 슬레이브 서버 표시 여부 감지에 실패했습니다.
*/
개인 함수 _isDeadServer($c) {
$cache = Yii::app()->{$this->cacheID};
if ($cache && $cache->get('DeadServer::' . $c) == 1) {
사실을 반환;
}
거짓을 반환;
}
/**
* 실패한 노예를 표시하세요
*/
개인 함수 _markDeadServer($c) {
$cache = Yii::app()->{$this->cacheID};
if ($cache) {
$cache->set('DeadServer::' . $c, 1, $this->markDeadSeconds);
}
}
}
main.php配置:구성 요소 数组中,代码如下:
'db'=>배열(
'class'=>'application.extensions.DbConnectionMan',//확장 경로
'connectionString' => 'mysql:host=192.168.1.128;dbname=db_xcpt',//기본 데이터베이스 쓰기
'emulatePrepare' => 참,
'사용자 이름' => '루트',
'비밀번호' => '루트',
'문자 집합' => 'utf8',
'tablePrefix' => 'xcpt_', //테이블 접두사
'enableSlave'=>true,//데이터베이스에서 활성화
'urgencyWrite'=>true,//긴급 상황 시 메인 데이터베이스에 연결할 수 없으므로 슬레이브 데이터베이스 쓰기 기능을 활성화하세요
'masterRead'=>true,//긴급상황 슬레이브 데이터베이스를 연결할 수 없습니다. 마스터 데이터베이스 읽기 기능을 활성화하세요
'노예'=>배열(//데이터베이스에서
배열( //슬레이브1
'connectionString'=>'mysql:host=localhost;dbname=db_xcpt',
'emulatePrepare' => 참,
'사용자 이름'=>'루트',
'비밀번호'=>'루트',
'문자 집합' => 'utf8',
'tablePrefix' => 'xcpt_', //테이블 접두사
),
배열( //슬레이브2
'connectionString'=>'mysql:host=localhost;dbname=db_xcpt',
'emulatePrepare' => 참,
'사용자 이름'=>'루트',
'비밀번호'=>'루트',
'문자 집합' => 'utf8',
'tablePrefix' => 'xcpt_', //테이블 접두사
),
),
),
이 기사가 Yii 프레임워크를 기반으로 하는 모든 사람의 PHP 프로그래밍에 도움이 되기를 바랍니다.