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实例
Dec 24 PHP
PHP修改session_id示例代码
Jan 08 PHP
php采集自中央气象台范围覆盖全国的天气预报代码实例
Jan 04 PHP
PHP获取ip对应地区和使用网络类型的方法
Mar 11 PHP
基础的WordPress插件制作教程
Nov 24 PHP
php fread读取文件注意事项
Sep 24 PHP
PHP获取用户客户端真实IP的解决方案
Oct 10 PHP
PHP isset()与empty()的使用区别详解
Feb 10 PHP
php使用str_shuffle()函数生成随机字符串的方法分析
Feb 17 PHP
php输出控制函数和输出函数生成静态页面
Jun 27 PHP
Laravel框架实现定时Task Scheduling例子
Oct 22 PHP
PHP加MySQL消息队列深入理解
Feb 27 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/12/30 PHP
mysql,mysqli,PDO的各自不同介绍
2012/09/19 PHP
PHP处理会话函数大总结
2015/08/05 PHP
详解PHP的Yii框架中日志的相关配置及使用
2015/12/08 PHP
PHP中OpenSSL加密问题整理
2017/12/14 PHP
JavaScript 核心参考教程 内置对象
2009/10/13 Javascript
window.name代替cookie的实现代码
2010/11/28 Javascript
JavaScript 实现类的多种方法实例
2013/05/01 Javascript
iframe子页面与父页面在同域或不同域下的js通信
2014/05/07 Javascript
jquery 实现input输入什么div图层显示什么
2014/06/15 Javascript
JavaScript中的Repaint和Reflow用法详解
2015/07/27 Javascript
z-blog SyntaxHighlighter 长代码无法换行解决办法(基于jquery)
2015/11/18 Javascript
Bootstrap每天必学之下拉菜单
2015/11/25 Javascript
JQuery异步提交表单与文件上传功能示例
2017/01/12 Javascript
解决淘宝cnpm 安装后cnpm不是内部或外部命令的问题
2018/05/17 Javascript
三分钟教你用Node做一个微信哄女友(基友)神器(面向小白)
2019/06/21 Javascript
vue中filters 传入两个参数 / 使用两个filters的实现方法
2019/07/15 Javascript
[01:15]PWL S2开团时刻第二期——他们杀 我就白给
2020/11/25 DOTA
Python MD5文件生成码
2009/01/12 Python
python 解析XML python模块xml.dom解析xml实例代码
2014/02/07 Python
python批量修改文件名的实现代码
2014/09/01 Python
Python实现建立SSH连接的方法
2015/06/03 Python
常用python编程模板汇总
2016/02/12 Python
Python算法应用实战之栈详解
2017/02/04 Python
Python标准库sched模块使用指南
2017/07/06 Python
pandas数值计算与排序方法
2018/04/12 Python
Python 十六进制整数与ASCii编码字符串相互转换方法
2018/07/09 Python
python调用支付宝支付接口流程
2019/08/15 Python
wxPython实现文本框基础组件
2019/11/18 Python
大四学生毕业自荐信
2013/11/07 职场文书
母亲节感恩寄语
2014/02/21 职场文书
小学语文业务学习材料
2014/06/02 职场文书
批评与自我批评范文
2014/10/15 职场文书
2019生态环境保护倡议书!
2019/07/03 职场文书
Ajax实现局部刷新的方法实例
2021/03/31 Javascript
React-vscode使用jsx语法的问题及解决方法
2021/06/21 Javascript