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 相关文章推荐
建立文件交换功能的脚本(三)
Oct 09 PHP
NO3第三帝国留言簿制作过程
Oct 09 PHP
sourcesafe管理phpproj文件的补充说明(downmoon)
Apr 11 PHP
php处理斐波那契数列非递归方法
Feb 04 PHP
基于PHP+Ajax实现表单验证的详解
Jun 25 PHP
PHP常用函数和常见疑难问题解答
Mar 05 PHP
PHP数字字符串左侧补0、字符串填充和自动补齐的几种方法
May 10 PHP
PHP使用Mysql事务实例解析
Sep 08 PHP
php计算一个文件大小的方法
Mar 30 PHP
PHP简单实现冒泡排序的方法
Dec 26 PHP
PHP迭代与递归实现无限级分类
Aug 28 PHP
PHP7数组的底层实现示例
Aug 25 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
php 求质素(素数) 的实现代码
2011/04/12 PHP
PHP模板引擎Smarty内置变量调解器用法详解
2016/04/11 PHP
ASP SQL防注入的方法
2008/12/25 Javascript
jquery的$(document).ready()和onload的加载顺序
2010/05/26 Javascript
基于jquery实现的表格分页实现代码
2011/06/21 Javascript
jQuery插件jQuery-JSONP开发ajax调用使用注意事项
2013/11/22 Javascript
删除javascript中注释语句的正则表达式
2014/06/11 Javascript
javascript操纵OGNL标签示例代码
2014/06/16 Javascript
初始Nodejs
2014/11/08 NodeJs
JS实现页面超时后自动跳转到登陆页面
2015/01/19 Javascript
JavaScript实现16进制颜色值转RGB的方法
2015/02/09 Javascript
Nodejs学习笔记之测试驱动
2015/04/16 NodeJs
JavaScript中实现Map的示例代码
2015/09/09 Javascript
jQuery实现简单的DIV拖动效果
2016/02/19 Javascript
JS实现快速的导航下拉菜单动画效果附源码下载
2016/11/01 Javascript
前端JS面试中常见的算法问题总结
2016/12/23 Javascript
vue.js 左侧二级菜单显示与隐藏切换的实例代码
2017/05/23 Javascript
解决betterScroll在vue中存在图片时,出现拉不动的问题
2018/09/27 Javascript
在element-ui的el-tree组件中用render函数生成el-button的实例代码
2018/11/05 Javascript
详解Vue依赖收集引发的问题
2019/04/22 Javascript
仿ElementUI实现一个Form表单的实现代码
2019/04/23 Javascript
vue 解决遍历对象显示的顺序不对问题
2019/11/07 Javascript
用python3 urllib破解有道翻译反爬虫机制详解
2019/08/14 Python
在OpenCV里使用Camshift算法的实现
2019/11/22 Python
Python实现分数序列求和
2020/02/25 Python
卡西欧G-SHOCK英国官网: 防水防震手表
2018/01/08 全球购物
有原因的手表:Flex Watches
2019/03/23 全球购物
经理秘书岗位职责
2013/11/14 职场文书
求职简历中自我评价
2014/01/28 职场文书
机工车间主任岗位职责
2014/03/05 职场文书
关爱老人标语
2014/06/21 职场文书
学校政风行风自查自纠报告
2014/10/21 职场文书
贷款担保书范本
2015/09/22 职场文书
校园安全学习心得体会
2016/01/18 职场文书
2016中秋节广告语
2016/01/28 职场文书
把77A收信机改造成收音机
2022/04/05 无线电