thinkphp下MySQL数据库读写分离代码剖析


Posted in PHP onApril 18, 2017

当采用原生态的sql语句进行写入操作的时候,要用execute,读操作要用query。

MySQL数据主从同步还是要靠MySQL的机制来实现,所以这个时候MySQL主从同步的延迟问题是需要优化,延迟时间太长不仅影响业务,还影响用户体验。

thinkphp核心类Thinkphp/library/Model.class.php 中,query 方法,调用Thinkphp/library/Think/Db/Driver/Mysql.class.php

/**
   * SQL查询
   * @access public
   * @param string $sql SQL
   * @param mixed $parse 是否需要解析SQL 
   * @return mixed
   */
  public function query($sql,$parse=false) {
    if(!is_bool($parse) && !is_array($parse)) {
      $parse = func_get_args();
      array_shift($parse);
    }
    $sql =  $this->parseSql($sql,$parse);
    return $this->db->query($sql);
  }

调用Thinkphp/library/Think/Db/Driver/Mysql.class.php

/**
   * 执行查询 返回数据集
   * @access public
   * @param string $str sql指令
   * @return mixed
   */
  public function query($str) {
    if(0===stripos($str, 'call')){ // 存储过程查询支持
      $this->close();
      $this->connected  =  false;
    }
    $this->initConnect(false);
    if ( !$this->_linkID ) return false;
    $this->queryStr = $str;
    //释放前次的查询结果
    if ( $this->queryID ) {  $this->free();  }
    N('db_query',1);
    // 记录开始执行时间
    G('queryStartTime');
    $this->queryID = mysql_query($str, $this->_linkID);
    $this->debug();
    if ( false === $this->queryID ) {
      $this->error();
      return false;
    } else {
      $this->numRows = mysql_num_rows($this->queryID);
      return $this->getAll();
    }
  }

上面初始化数据库链接时,initConnect(false),调用Thinkphp/library/Think/Db/Db.class.php,注意false、true代码实现。true表示直接调用主库,false表示调用读写分离的读库。

/**
   * 初始化数据库连接
   * @access protected
   * @param boolean $master 主服务器
   * @return void
   */
  protected function initConnect($master=true) {
    if(1 == C('DB_DEPLOY_TYPE'))
      // 采用分布式数据库
      $this->_linkID = $this->multiConnect($master);
    else
      // 默认单数据库
      if ( !$this->connected ) $this->_linkID = $this->connect();
  }

  /**
   * 连接分布式服务器
   * @access protected
   * @param boolean $master 主服务器
   * @return void
   */
  protected function multiConnect($master=false) {
    foreach ($this->config as $key=>$val){
      $_config[$key]   =  explode(',',$val);
    }    
    // 数据库读写是否分离
    if(C('DB_RW_SEPARATE')){
      // 主从式采用读写分离
      if($master)
        // 主服务器写入
        $r =  floor(mt_rand(0,C('DB_MASTER_NUM')-1));
      else{
        if(is_numeric(C('DB_SLAVE_NO'))) {// 指定服务器读
          $r = C('DB_SLAVE_NO');
        }else{
          // 读操作连接从服务器
          $r = floor(mt_rand(C('DB_MASTER_NUM'),count($_config['hostname'])-1));  // 每次随机连接的数据库
        }
      }
    }else{
      // 读写操作不区分服务器
      $r = floor(mt_rand(0,count($_config['hostname'])-1));  // 每次随机连接的数据库
    }
    $db_config = array(
      'username' => isset($_config['username'][$r])?$_config['username'][$r]:$_config['username'][0],
      'password' => isset($_config['password'][$r])?$_config['password'][$r]:$_config['password'][0],
      'hostname' => isset($_config['hostname'][$r])?$_config['hostname'][$r]:$_config['hostname'][0],
      'hostport' => isset($_config['hostport'][$r])?$_config['hostport'][$r]:$_config['hostport'][0],
      'database' => isset($_config['database'][$r])?$_config['database'][$r]:$_config['database'][0],
      'dsn'    => isset($_config['dsn'][$r])?$_config['dsn'][$r]:$_config['dsn'][0],
      'params'  => isset($_config['params'][$r])?$_config['params'][$r]:$_config['params'][0],
      'charset'  => isset($_config['charset'][$r])?$_config['charset'][$r]:$_config['charset'][0],      
    );
    return $this->connect($db_config,$r);
  }

query方法参数为false,其他删除、更新、增加读主库。这一点可以结合Thinkphp/library/Model.class.php中的delete、save、add操作,参数为true。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
PHP文件注释标记及规范小结
Apr 01 PHP
工厂模式在Zend Framework中应用介绍
Jul 10 PHP
CURL的学习和应用(附多线程实现)
Jun 03 PHP
单点登录 Ucenter示例分析
Oct 29 PHP
PHP管理依赖(dependency)关系工具 Composer的自动加载(autoload)
Aug 18 PHP
php打造智能化的柱状图程序,用于报表等
Jun 19 PHP
PHP验证码生成原理和实现
Jan 24 PHP
Yii框架防止sql注入,xss攻击与csrf攻击的方法
Oct 18 PHP
php array_pop 删除数组最后一个元素实例
Nov 02 PHP
Yii2框架制作RESTful风格的API快速入门教程
Nov 08 PHP
php解决DOM乱码的方法示例代码
Nov 20 PHP
php中文语义分析实现方法示例
Sep 28 PHP
Thinkphp通过一个入口文件如何区分移动端和PC端
Apr 18 #PHP
Yii2汉字转拼音类的实例代码
Apr 18 #PHP
php+resumablejs实现的分块上传 断点续传功能示例
Apr 18 #PHP
ZendFramework2连接数据库操作实例
Apr 18 #PHP
PHP实现的数独求解问题示例
Apr 18 #PHP
PHP使用finfo_file()函数检测上传图片类型的实现方法
Apr 18 #PHP
php实现不通过扩展名准确判断文件类型的方法【finfo_file方法与二进制流】
Apr 18 #PHP
You might like
基于OpenCV的PHP图像人脸识别技术
2009/10/11 PHP
php中一个有意思的日期逻辑处理
2012/03/25 PHP
kohana框架上传文件验证规则写法示例
2014/07/14 PHP
php递归json类实例
2014/12/02 PHP
编写PHP脚本过滤用户上传的图片
2015/07/03 PHP
Yii2验证器(Validator)用法分析
2016/07/23 PHP
浅谈PHP array_search 和 in_array 函数效率问题
2019/10/15 PHP
jQuery中需要注意的细节问题小结
2011/12/06 Javascript
js异常捕获方法介绍
2013/04/10 Javascript
js单词形式的运算符
2014/05/06 Javascript
AngularJs $parse、$eval和$observe、$watch详解
2016/09/21 Javascript
Vue非父子组件通信详解
2017/06/12 Javascript
用最少的JS代码写出贪吃蛇游戏
2018/01/12 Javascript
vuex实现登录状态的存储,未登录状态不允许浏览的方法
2018/03/09 Javascript
JS加密插件CryptoJS实现的Base64加密示例
2020/08/16 Javascript
vuex实现的简单购物车功能示例
2019/02/13 Javascript
Vue.js + Nuxt.js 项目中使用 Vee-validate 表单校验
2019/04/22 Javascript
24个ES6方法解决JS实际开发问题(小结)
2020/05/31 Javascript
基于jquery实现彩色投票进度条代码解析
2020/08/26 jQuery
nodejs中使用worker_threads来创建新的线程的方法
2021/01/22 NodeJs
python dataframe常见操作方法:实现取行、列、切片、统计特征值
2018/06/09 Python
三步实现Django Paginator分页的方法
2019/06/11 Python
python requests更换代理适用于IP频率限制的方法
2019/08/21 Python
pytorch 实现在一个优化器中设置多个网络参数的例子
2020/02/20 Python
浅谈keras中的目标函数和优化函数MSE用法
2020/06/10 Python
解析python 中/ 和 % 和 //(地板除)
2020/06/28 Python
Django model class Meta原理解析
2020/11/14 Python
css3弹性盒模型实例介绍
2013/05/27 HTML / CSS
CAT鞋美国官网:CAT Footwear
2017/11/27 全球购物
Bluebella法国官网:英国性感内衣品牌
2019/05/03 全球购物
2014年小学教导处工作总结
2014/12/19 职场文书
幼儿园教师求职信
2015/03/20 职场文书
最美劳动诗,致敬所有的劳动者!
2019/07/12 职场文书
如果用一句诗总结你的上半年,你会用哪句呢?
2019/07/16 职场文书
一定要知道的 25 个 Vue 技巧
2021/11/02 Vue.js
微信小程序 WeUI扩展组件库的入门教程
2022/04/21 Javascript