之前有提到 discuz x3 开启 db主从后 报bug导致无法 正常使用 后来通过修改
// source/class/db/db_driver_mysql_slave.php 参数设置为1
解决 。
本周深入了解了下 原来是因为 二次开发的时候 某些不是很规范的写法引起的:
db查询的时候没有使用 discuz 提供的 DB::table 导致。
修正完毕后 就可以正常使用了。
在这里转一篇关于 discuz 主从原理的文章
/source/class/class_core.php
当配置了从库信息时,直接连接从库
discuz_core::_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(); }
db_mysql::table_name
table_name方法,每次将数据库连接curlink重置了主库连接。
其中$this->map为对数据库分库的配置,哪些表适用哪一个数据库,然后建立连接。
function table_name($tablename) { if(!empty($this->map) && !empty($this->map[$tablename])) { $id = $this->map[$tablename]; if(!$this->link[$id]) { $this->connect($id); } $this->curlink = $this->link[$id]; } else { $this->curlink = $this->link[1]; } return $this->tablepre.$tablename; }
DB::table
此方法调用db_mysql::table_name方法
function table($table) { return DB::_execute('table_name', $table); }
/source/class/class_mysql_slave.php
db_mysql_slave::table_name
slave的table方法,判断表是否在“slave_except_table”中,slave_except_table为配置的不使用从库连接的数据表
function table_name($tablename) { if($this->slaveid && !$this->slaveexcept && $this->excepttables) { if(in_array($tablename, $this->excepttables)) { $this->slaveexcept = true; } }
db_mysql_slave::query
slave的query方法,判段没有配置不使用从库的表,且sql语句为select时,才将curlink指向从库,否则curlink仍执行主库。
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); }
总结:
1. 在扩展或做插件,使用数据库操作时,使用“DB::table($tablename)”来获取表名拼接sql就能兼容Discuz!X的主从库配置
2. 若仅使用主库连接,系统不会使用到db_mysql_save的类
3. 每次页面请求,只有一个db对象。 使用connect和设置curlink来实现主从连接
转载自:
http://discuzx.sinaapp.com/thread-12-1-1.html
感谢楼主分享。