加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

Yii多数据库主从读写分离实例详解

发布时间:2022-07-05 15:58:01 所属栏目:PHP教程 来源:互联网
导读:Yii框架数据库多数据库、主从、读写分离 实现,功能描述: 1.实现主从数据库读写分离 主库:写 从库(可多个):读 2.主数据库无法连接时 可设置从数据库是否 可写 3.所有从数据库无法连接时 可设置主数据库是否 可读 4.如果从数据库连接失败 可设置N秒内不再连
  Yii框架数据库多数据库、主从、读写分离 实现,功能描述:
 
  1.实现主从数据库读写分离 主库:写 从库(可多个):读
 
  2.主数据库无法连接时 可设置从数据库是否 可写
 
  3.所有从数据库无法连接时 可设置主数据库是否 可读
 
  4.如果从数据库连接失败 可设置N秒内不再连接
 
  利用yii扩展实现,代码如下:
 
  <?php
  /**
       /**
       * @var array $slaves.Slave database connection(Read) config array.
       * 配置符合 CDbConnection.
       * @example
       * 'components'=>array(
       *   'db'=>array(
       *    'connectionString'=>'mysql://<master>',
       *    'slaves'=>array(
       *     array('connectionString'=>'mysql://<slave01>'),
       *     array('connectionString'=>'mysql://<slave02>'),
       *    )
       *   )
       * )
       * */
      public $slaves = array();
   
      /**
       *  
       * 从数据库状态 false 则只用主数据库
       * @var bool $enableSlave
       * */
      public $enableSlave = true;
   
      /**
       private $_disableWrite = true;
   
      /**
       *
       * 重写 createCommand 方法,1.开启从库 2.存在从库 3.当前不处于一个事务中 4.从库读数据
       * @param string $sql
       * @return CDbCommand
       * */
      public function 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("Master db server is not available now!Disallow write operation on slave server!");
                  }
              }
              return parent::createCommand($sql);
          }
      }
   
      /**
       * 获得从服务器连接资源
       * @return CDbConnection
       * */
      public function getSlave() {
   
                   try {
                      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 = $slave;
                          break;
                      }
                  } catch (Exception $e) {
                      $this->_markDeadServer($slaveConfig['connectionString']);
                      Yii::log("Slave database connection failed!ntConnection string:{$slaveConfig['connectionString']}", 'warning');
   
                      continue;
                  }
              }
   
              if (!isset($this->_slave)) {
                  $this->_slave = null;
                  $this->enableSlave = false;
              }
          }
          return $this->_slave;
      }
   
      public function setActive($value) {
          if ($value != $this->getActive()) {
              if ($value) {
                  try {
                      if ($this->_isDeadServer($this->connectionString)) {
                          throw new CDbException('Master db server is already dead!');
                      }
                      //PDO::ATTR_TIMEOUT must set before pdo instance create
                      $this->setAttribute(PDO::ATTR_TIMEOUT, $this->timeout);
                      $this->open();
                           $this->open();
                      } else { //Slave also unavailable
                          if ($this->masterRead) {
                              $this->connectionString = $this->connectionString;
                              $this->username = $this->username;
                              $this->password = $this->password;
                              $this->open();
                          } else {
                              throw new CDbException(Yii::t('yii', 'CDbConnection failed to open the DB connection.'), (int) $e->getCode(), $e->errorInfo);
                          }
                      }
                  }
              } else {
                  $this->close();
              }
          }
      }
   
      /**
       * 检测读操作 sql 语句
       *  
       * 关键字: SELECT,DECRIBE,SHOW ...
       * 写操作:UPDATE,INSERT,DELETE ...
       * */
      public static function isReadOperation($sql) {
          $sql = substr(ltrim($sql), 0, 10);
       private function _isDeadServer($c) {
          $cache = Yii::app()->{$this->cacheID};
          if ($cache && $cache->get('DeadServer::' . $c) == 1) {
              return true;
          }
          return false;
      }
   
      /**
       * 标记失败的slaves.
       */
      private function _markDeadServer($c) {
      //开源代码phpfensi.com
          $cache = Yii::app()->{$this->cacheID};
          if ($cache) {
              $cache->set('DeadServer::' . $c, 1, $this->markDeadSeconds);
          }
      }
   
  } 

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读