在 Discuz! X 版本 程式裡面內建了讀寫分離的功能,方便了一些負載比較大的站點使用來降低一定的負載。

Discuz! X 2.0 預設未開啟此功能,需要在配置檔案中做相應的修改此功能才會開啟生效。

在配置開啟讀寫分離的之前需要在伺服器上先配置好 mysql 的主從

下面介紹一下 X2 讀寫分離的配置:

X2 的讀寫分離只需要在 ./config/config_global.php 檔案中加入,以下的內容即可

  1. $_config['db']['slave'] = array();
  2. $_config['db']['slave']['1']['dbhost'] = '10.0.4.162';  //mysql 從庫的 host
  3. $_config['db']['slave']['1']['dbuser'] = 'formaster';   //mysql 從庫的資料庫使用者名稱
  4. $_config['db']['slave']['1']['dbpw'] = '****';    //mysql 從庫的資料庫密碼
  5. $_config['db']['slave']['1']['dbcharset'] = 'gbk';
  6. $_config['db']['slave']['1']['pconnect'] = '0';
  7. $_config['db']['slave']['1']['dbname'] = 'ultrax'; //mysql 從庫的資料庫名
  8. $_config['db']['slave']['1']['tablepre'] = 'pre_';
  9. //如果有多臺從庫可以繼續新增
  10. //$_config['db']['slave']['2']['dbhost'] = 'xxx';
  11. //$_config['db']['slave']['2']['dbuser'] = 'xxxxxx';
  12. //...
  13. $_config['db']['common']['slave_except_table'] = '';  //以逗句分離的表名,表示此處設定的表僅從主伺服器讀寫, 不使用從伺服器讀取

在 X2 的程式中每個入口檔案都會先執行 $discuz->init(); 在該方法裡中呼叫的 內部方法 _init_db()

  1.         function _init_db() {
  2.                 $class = 'db_mysql';
  3.                 if(count(getglobal('config/db/slave'))) {
  4.                         require_once libfile('class/mysql_slave');
  5.                         $class = 'db_mysql_slave';
  6.                 }
  7.                 $this->db = & DB::object($class);
  8.                 $this->db->set_config($this->config['db']);
  9.                 $this->db->connect();
  10.         }

會先 count(getglobal('config/db/slave')) 判斷 config_global.php 中是否配置了 slave

如果配置了則會呼叫 ./source/class/class_mysql_slave.php 檔案中的 db_mysql 的子類 db_mysql_slave 代替 db_mysql

當程式執行 query 時 調到 db_mysql_slave 的 query 方法

  1.         function query($sql, $type = '') {
  2.                 if($this->slaveid && !$this->slaveexcept && strtoupper(substr($sql, 0 , 6)) == 'SELECT') {
  3.                         $this->slave_connect();
  4.                 }
  5.                 $this->slaveexcept = false;
  6.                 return parent::query($sql, $type);
  7.         }

此方法中判斷了 非 $_config['db']['common']['slave_except_table']   中設定的表及 為 SELECT 查詢語句時使用從庫的連線從從庫查詢資料,其他則用預設的使用主庫

如果在使用過程中有發現一些異常,或者想控制相關的 sql 語句讀取的資料庫,可以嘗試在此方法中判斷 $sql 的語句內容 來指定其需要讀的主庫 還是 從庫