>  기사  >  백엔드 개발  >  여러 데이터베이스에서 마스터-슬레이브 읽기 및 쓰기 분리를 구현하는 Yii 방법_php 예제

여러 데이터베이스에서 마스터-슬레이브 읽기 및 쓰기 분리를 구현하는 Yii 방법_php 예제

WBOY
WBOY원래의
2016-05-16 20:26:55843검색

이 기사의 예에서는 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 프로그래밍에 도움이 되기를 바랍니다.

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.