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
PHP4之COOKIE支持详解
Oct 09 PHP
PHP入门学习的几个不错的实例代码
Jul 13 PHP
php mssql 时间格式问题
Jan 13 PHP
php获取一个变量的名字的方法
Sep 05 PHP
php中json_encode UTF-8中文乱码的更好解决方法
Sep 28 PHP
8个PHP程序员常用的功能汇总
Dec 18 PHP
php绘制圆形的方法
Jan 24 PHP
PHP使用内置dir类实现目录遍历删除
Mar 31 PHP
PHP实现的DES加密解密实例代码
Apr 06 PHP
PHP结合Ffmpeg快速搭建流媒体服务的实践记录
Oct 31 PHP
TP5框架页面跳转样式操作示例
Apr 05 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
MySql中正则表达式的使用方法描述
2008/07/30 PHP
在html文件中也可以执行php语句的方法
2015/04/09 PHP
百度工程师讲PHP函数的实现原理及性能分析(一)
2015/05/13 PHP
php实现通过ftp上传文件
2015/06/19 PHP
基于Swoole实现PHP与websocket聊天室
2016/08/03 PHP
JavaScript 继承详解(一)
2009/07/13 Javascript
基于jquery的二级联动菜单实现代码
2011/04/25 Javascript
JS文本框不能输入空格验证方法
2013/03/19 Javascript
JavaScript实现按Ctrl键打开新页面
2014/09/04 Javascript
Jquery实现仿腾讯微博发表广播
2014/11/17 Javascript
jQuery 回调函数(callback)的使用和基础
2015/02/26 Javascript
JS中split()用法(将字符串按指定符号分割成数组)
2016/10/24 Javascript
EditPlus 正则表达式 实战(3)
2016/12/15 Javascript
JS常见简单正则表达式验证功能小结【手机,地址,企业税号,金额,身份证等】
2017/01/22 Javascript
jquery uploadify如何取消已上传成功文件
2017/02/08 Javascript
vue.js实现备忘录功能的方法
2017/07/10 Javascript
JavaScript学习笔记之函数记忆
2017/09/06 Javascript
Node.js学习之地址解析模块URL的使用详解
2017/09/28 Javascript
Vue CLI 3搭建vue+vuex最全分析(推荐)
2018/09/27 Javascript
JavaScript 继承 封装 多态实现及原理详解
2019/07/29 Javascript
基于Express框架使用POST传递Form数据
2019/08/10 Javascript
python多线程编程方式分析示例详解
2013/12/06 Python
Python 列表list使用介绍
2014/11/30 Python
Python 使用requests模块发送GET和POST请求的实现代码
2016/09/21 Python
Python使用arrow库优雅地处理时间数据详解
2017/10/10 Python
Python一行代码解决矩阵旋转的问题
2019/11/30 Python
浅谈JupyterNotebook导出pdf解决中文的问题
2020/04/22 Python
Python如何优雅删除字符列表空字符及None元素
2020/06/25 Python
HTML5实现多张图片上传功能
2016/03/11 HTML / CSS
英国奢侈皮具品牌:Aspinal of London
2018/09/02 全球购物
安全生产实施方案
2014/02/23 职场文书
本科生自荐信
2014/06/18 职场文书
个人四风问题原因分析及整改措施
2014/09/28 职场文书
公安机关查摆剖析材料
2014/10/10 职场文书
2015年高校辅导员工作总结
2015/04/20 职场文书
Unity连接MySQL并读取表格数据的实现代码
2021/06/20 MySQL