在 Discuz! X版本 程序里面內置了讀寫分離的功能,方便了一些負載比較大的站點使用來降低一定的負載.
Discuz! X 默認未開啟此功能,需要在配置文件中做相應的修改此功能才會開啟生效。
在配置開啟讀寫分離的之前需要在服務器上先配置好 mysql 的主從下面介紹一下讀寫分離的配置:
讀寫分離只需要在 ./config/config_global.php 文件中加入,以下的內容即可:
- $_config['db']['slave'] = array();
- $_config['db']['slave']['1']['dbhost'] = '10.0.4.162'; //mysql 從庫的host
- $_config['db']['slave']['1']['dbuser'] = 'formaster'; //mysql 從庫的數據庫用戶名
- $_config['db']['slave']['1']['dbpw'] = '****'; //mysql 從庫的數據庫密碼
- $_config['db']['slave']['1']['dbcharset'] = 'gbk';
- $_config['db']['slave']['1']['pconnect'] = '0';
- $_config['db']['slave']['1']['dbname'] = 'ultrax'; //mysql從庫的數據庫名
- $_config['db']['slave']['1']['tablepre'] = 'pre_';
- //如果有多臺從庫可以繼續添加
- //$_config['db']['slave']['2']['dbhost'] = 'xxx';
- //$_config['db']['slave']['2']['dbuser'] = 'xxxxxx';
- //...
- $_config['db']['common']['slave_except_table'] = ''; //以逗句分離的表名,表示此處設置的表僅從主服務器讀寫, 不使用從服務器讀取
在程序中每個入口文件都會先執行 $discuz->init(); 在該方法里中調用的 內部方法 _init_db():
- function _init_db() {
- $class = 'db_mysql';
- if(count(getglobal('config/db/slave'))) {
- require_once libfile('class/mysql_slave');
- $class = 'db_mysql_slave';
- }
- $this->db = & DB::object($class);
- $this->db->set_config($this->config['db']);
- $this->db->connect();
會先 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方法:
- function query($sql, $type = '') {
- if($this->slaveid && !$this->slaveexcept && strtoupper(substr($sql, 0 , 6)) == 'SELECT') {
- $this->slave_connect();
- }
- $this->slaveexcept = false;
- return parent::query($sql, $type);
- }
此方法中判斷了 非 $_config['db']['common']['slave_except_table'] 中設置的表及 為 SELECT 查詢語句時使用從庫的連接從從庫查詢數據,其他則用默認的使用主庫.
如果在使用過程中有發現一些異常,或者想控制相關的 sql 語句讀取的數據庫,可以嘗試在此方法中判斷 $sql 的語句內容 來指定其需要讀的主庫還是從庫.
新聞熱點
疑難解答