国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > PHP > 正文

Yii多數據庫主從讀寫分離實例介紹

2024-05-04 21:49:09
字體:
來源:轉載
供稿:網友

Yii框架數據庫多數據庫、主從、讀寫分離 實現,功能描述:

1.實現主從數據庫讀寫分離 主庫:寫 從庫(可多個):讀

2.主數據庫無法連接時 可設置從數據庫是否 可寫

3.所有從數據庫無法連接時 可設置主數據庫是否 可讀

4.如果從數據庫連接失敗 可設置N秒內不再連接

利用yii擴展實現,代碼如下:

  1. <?php
  2. /** 
  3.  * 主數據庫 寫 從數據庫(可多個)讀 
  4.  * 實現主從數據庫 讀寫分離 主服務器無法連接 從服務器可切換寫功能 
  5.  * 從務器無法連接 主服務器可切換讀功 
  6.  * by lmt 
  7.  * */ 
  8. class DbConnectionMan extends CDbConnection { 
  9.  
  10.     public $timeout = 10; //連接超時時間 
  11.     public $markDeadSeconds = 600; //如果從數據庫連接失敗 600秒內不再連接  
  12.     //用 cache 作為緩存全局標記 
  13.     public $cacheID = 'cache'
  14.  
  15.     /** 
  16.      * @var array $slaves.Slave database connection(Read) config array. 
  17.      * 配置符合 CDbConnection. 
  18.      * @example 
  19.      * 'components'=>array( 
  20.      *   'db'=>array( 
  21.      *    'connectionString'=>'mysql://<master>', 
  22.      *    'slaves'=>array( 
  23.      *     array('connectionString'=>'mysql://<slave01>'), 
  24.      *     array('connectionString'=>'mysql://<slave02>'), 
  25.      *    ) 
  26.      *   ) 
  27.      * ) 
  28.      * */ 
  29.     public $slaves = array(); 
  30.  
  31.     /** 
  32.      *  
  33.      * 從數據庫狀態 false 則只用主數據庫 
  34.      * @var bool $enableSlave 
  35.      * */ 
  36.     public $enableSlave = true; 
  37.  
  38.     /** 
  39.      * @var slavesWrite 緊急情況主數據庫無法連接 切換從服務器(讀寫). 
  40.      */ 
  41.     public $slavesWrite = false; 
  42.  
  43.     /** 
  44.      * @var masterRead 緊急情況從主數據庫無法連接 切換從住服務器(讀寫). 
  45.      */ 
  46.     public $masterRead = false; 
  47.  
  48.     /** 
  49.      * @var _slave 
  50.      */ 
  51.     private $_slave
  52.  
  53.     /** 
  54.      * @var _disableWrite 從服務器(只讀). 
  55.      */ 
  56.     private $_disableWrite = true; 
  57.  
  58.     /** 
  59.      * 
  60.      * 重寫 createCommand 方法,1.開啟從庫 2.存在從庫 3.當前不處于一個事務中 4.從庫讀數據 
  61.      * @param string $sql 
  62.      * @return CDbCommand 
  63.      * */ 
  64.     public function createCommand($sql = null) { 
  65.         if ($this->enableSlave && !emptyempty($this->slaves) && is_string($sql) && !$this->getCurrentTransaction() && self::isReadOperation($sql) && ($slave = $this->getSlave()) 
  66.         ) { 
  67.             return $slave->createCommand($sql); 
  68.         } else { 
  69.             if (!$this->masterRead) { 
  70.                 if ($this->_disableWrite && !self::isReadOperation($sql)) { 
  71.  
  72.                     throw new CDbException("Master db server is not available now!Disallow write operation on slave server!"); 
  73.                 } 
  74.             } 
  75.             return parent::createCommand($sql); 
  76.         } 
  77.     } 
  78.  
  79.     /** 
  80.      * 獲得從服務器連接資源 
  81.      * @return CDbConnection 
  82.      * */ 
  83.     public function getSlave() { 
  84.  
  85.         if (!isset($this->_slave)) { 
  86.  
  87.             shuffle($this->slaves); 
  88.             foreach ($this->slaves as $slaveConfig) { 
  89.  
  90.                 if ($this->_isDeadServer($slaveConfig['connectionString'])) { 
  91.                     continue
  92.                 } 
  93.                 if (!isset($slaveConfig['class'])) 
  94.                     $slaveConfig['class'] = 'CDbConnection'
  95.  
  96.                 $slaveConfig['autoConnect'] = false; 
  97.                 try { 
  98.                     if ($slave = Yii::createComponent($slaveConfig)) { 
  99.                         Yii::app()->setComponent('dbslave'$slave); 
  100.                         $slave->setAttribute(PDO::ATTR_TIMEOUT, $this->timeout); 
  101.                         $slave->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); 
  102.                         $slave->setActive(true); 
  103.                         $this->_slave = $slave
  104.                         break
  105.                     } 
  106.                 } catch (Exception $e) { 
  107.                     $this->_markDeadServer($slaveConfig['connectionString']); 
  108.                     Yii::log("Slave database connection failed!ntConnection string:{$slaveConfig['connectionString']}"'warning'); 
  109.  
  110.                     continue
  111.                 } 
  112.             } 
  113.  
  114.             if (!isset($this->_slave)) { 
  115.                 $this->_slave = null; 
  116.                 $this->enableSlave = false; 
  117.             } 
  118.         } 
  119.         return $this->_slave; 
  120.     } 
  121.  
  122.     public function setActive($value) { 
  123.         if ($value != $this->getActive()) { 
  124.             if ($value) { 
  125.                 try { 
  126.                     if ($this->_isDeadServer($this->connectionString)) { 
  127.                         throw new CDbException('Master db server is already dead!'); 
  128.                     } 
  129.                     //PDO::ATTR_TIMEOUT must set before pdo instance create 
  130.                     $this->setAttribute(PDO::ATTR_TIMEOUT, $this->timeout); 
  131.                     $this->open(); 
  132.                 } catch (Exception $e) { 
  133.                     $this->_markDeadServer($this->connectionString); 
  134.                     $slave = $this->getSlave(); 
  135.                     Yii::log($e->getMessage(), CLogger::LEVEL_ERROR, 'exception.CDbException'); 
  136.                     if ($slave) { 
  137.                         $this->connectionString = $slave->connectionString; 
  138.                         $this->username = $slave->username; 
  139.                         $this->password = $slave->password; 
  140.                         if ($this->slavesWrite) { 
  141.                             $this->_disableWrite = false; 
  142.                         } 
  143.                         $this->open(); 
  144.                     } else { //Slave also unavailable 
  145.                         if ($this->masterRead) { 
  146.                             $this->connectionString = $this->connectionString; 
  147.                             $this->username = $this->username; 
  148.                             $this->password = $this->password; 
  149.                             $this->open(); 
  150.                         } else { 
  151.                             throw new CDbException(Yii::t('yii''CDbConnection failed to open the DB connection.'), (int) $e->getCode(), $e->errorInfo); 
  152.                         } 
  153.                     } 
  154.                 } 
  155.             } else { 
  156.                 $this->close(); 
  157.             } 
  158.         } 
  159.     } 
  160.  
  161.     /** 
  162.      * 檢測讀操作 sql 語句 
  163.      *  
  164.      * 關鍵字: SELECT,DECRIBE,SHOW ... 
  165.      * 寫操作:UPDATE,INSERT,DELETE ... 
  166.      * */ 
  167.     public static function isReadOperation($sql) { 
  168.         $sql = substr(ltrim($sql), 0, 10); 
  169.         $sql = str_ireplace(array('SELECT''SHOW''DESCRIBE''PRAGMA'), '^O^'$sql); //^O^,magic smile 
  170.         return strpos($sql'^O^') === 0; 
  171.     } 
  172.  
  173.     /** 
  174.      * 檢測從服務器是否被標記 失敗. 
  175.      */ 
  176.     private function _isDeadServer($c) { 
  177.         $cache = Yii::app()->{$this->cacheID}; 
  178.         if ($cache && $cache->get('DeadServer::' . $c) == 1) { 
  179.             return true; 
  180.         } 
  181.         return false; 
  182.     } 
  183.  
  184.     /** 
  185.      * 標記失敗的slaves. 
  186.      */ 
  187.     private function _markDeadServer($c) { 
  188.     //開源代碼Vevb.com 
  189.         $cache = Yii::app()->{$this->cacheID}; 
  190.         if ($cache) { 
  191.             $cache->set('DeadServer::' . $c, 1, $this->markDeadSeconds); 
  192.         } 
  193.     } 
  194.  

main.php配置:components 數組中,代碼如下:

  1. 'db'=>array
  2.         'class'=>'application.extensions.DbConnectionMan',//擴展路徑 
  3.         'connectionString' => 'mysql:host=192.168.1.128;dbname=db_xcpt',//主數據庫 寫 
  4.         'emulatePrepare' => true, 
  5.         'username' => 'root'
  6.         'password' => 'root'
  7.         'charset' => 'utf8'
  8.         'tablePrefix' => 'xcpt_'//表前綴 
  9.         'enableSlave'=>true,//從數據庫啟用 
  10.    'urgencyWrite'=>true,//緊急情況 主數據庫無法連接 啟用從數據庫 寫功能 
  11.     'masterRead'=>true,//緊急情況 從數據庫無法連接 啟用主數據庫 讀功能 
  12.         'slaves'=>array(//從數據庫 
  13.             array(   //slave1 
  14.                 'connectionString'=>'mysql:host=localhost;dbname=db_xcpt'
  15.                 'emulatePrepare' => true, 
  16.                 'username'=>'root'
  17.                 'password'=>'root'
  18.                 'charset' => 'utf8'
  19.                 'tablePrefix' => 'xcpt_'//表前綴 
  20.             ), 
  21.    array(   //slave2 
  22.                 'connectionString'=>'mysql:host=localhost;dbname=db_xcpt'
  23.                 'emulatePrepare' => true, 
  24.                 'username'=>'root'
  25.                 'password'=>'root'
  26.                 'charset' => 'utf8'
  27.                 'tablePrefix' => 'xcpt_'//表前綴 
  28.             ), 
  29.  
  30.         ), 
  31.     ),

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 冀州市| 图木舒克市| 固镇县| 鹿邑县| 小金县| 灵宝市| 进贤县| 天镇县| 裕民县| 上蔡县| 本溪市| 和林格尔县| 乃东县| 临朐县| 聂拉木县| 明光市| 独山县| 牙克石市| 桃江县| 吉木萨尔县| 霍林郭勒市| 九龙坡区| 崇信县| 木里| 安国市| 乌鲁木齐县| 织金县| 红河县| 泰顺县| 呼和浩特市| 施秉县| 张家口市| 福贡县| 凉山| 宁河县| 淅川县| 盐边县| 隆安县| 潮安县| 夏津县| 安福县|