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 相关文章推荐
PHPCMS的使用小结
Sep 20 PHP
php设计模式 Decorator(装饰模式)
Jun 26 PHP
PHP实现异步调用方法研究与分享
Oct 27 PHP
php的array_multisort()使用方法介绍
May 16 PHP
php导出csv格式数据并将数字转换成文本的思路以及代码分享
Jun 05 PHP
destoon设置自定义搜索的方法
Jun 21 PHP
ThinkPHP模板替换与系统常量及应用实例教程
Aug 22 PHP
Yii入门教程之目录结构、入口文件及路由设置
Nov 25 PHP
php5.4以上版本GBK编码下htmlspecialchars输出为空问题解决方法汇总
Apr 03 PHP
PHP中set error handler函数用法小结
Nov 11 PHP
PHP获取二叉树镜像的方法
Jan 17 PHP
关于ThinkPHP中的异常处理详解
May 11 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中addslashes()和stripslashes()实现字符串转义和还原用法实例
2016/01/07 PHP
PHP时间戳格式全部汇总 (获取时间、时间戳)
2016/06/13 PHP
php使用函数pathinfo()、parse_url()和basename()解析URL
2016/11/25 PHP
thinkPHP5.0框架API优化后的友好性分析
2017/03/17 PHP
php回调函数处理数组操作示例
2020/04/13 PHP
用Laravel轻松处理千万级数据的方法实现
2020/12/25 PHP
分享20款好玩的jQuery游戏
2011/04/17 Javascript
JQuery获取浏览器窗口内容部分高度的代码
2012/02/24 Javascript
javascript正则表达式基础知识入门
2015/04/20 Javascript
vue component组件使用方法详解
2017/07/14 Javascript
Node.js pipe实现源码解析
2017/08/12 Javascript
基于模板引擎Jade的应用(详解)
2017/12/12 Javascript
Bootstrap-table使用footerFormatter做统计列功能
2018/09/07 Javascript
js canvas画布实现高斯模糊效果
2018/11/27 Javascript
简单了解vue中的v-if和v-show的区别
2019/10/08 Javascript
Vue项目打包部署到iis服务器的配置方法
2019/10/14 Javascript
Vue router安装及使用方法解析
2020/12/02 Vue.js
浅谈使用Python变量时要避免的3个错误
2017/10/30 Python
Python FTP两个文件夹间的同步实例代码
2018/05/25 Python
Python简单过滤字母和数字的方法小结
2019/01/09 Python
Python3解释器知识点总结
2019/02/19 Python
Python循环中else,break和continue的用法实例详解
2019/07/11 Python
Django的models中on_delete参数详解
2019/07/16 Python
python数据处理之如何选取csv文件中某几行的数据
2019/09/02 Python
详解使用Python写一个向数据库填充数据的小工具(推荐)
2020/09/11 Python
python 实现Harris角点检测算法
2020/12/11 Python
利用纯CSS3实现动态的自行车特效源码
2017/01/20 HTML / CSS
深入解析HTML5 Canvas控制图形矩阵变换的方法
2016/03/24 HTML / CSS
美国流行背包品牌:JanSport(杰斯伯)
2018/03/02 全球购物
会计与审计专业大专生求职信
2013/10/03 职场文书
父亲追悼会答谢词
2014/01/17 职场文书
竞选班干部演讲稿500字
2014/08/20 职场文书
高中课前三分钟演讲稿
2014/09/13 职场文书
离婚协议书范文
2015/01/26 职场文书
投诉信范文
2015/07/02 职场文书
工作转正自我鉴定范文
2019/06/21 职场文书