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 download.php实现代码 跳转到下载文件(response.redirect)
Aug 26 PHP
thinkphp模板的包含与渲染实例分析
Nov 26 PHP
PHP采集静态页面并把页面css,img,js保存的方法
Dec 23 PHP
php内存缓存实现方法
Jan 24 PHP
用PHP生成excel文件到指定目录
Jun 22 PHP
thinkphp微信开发(消息加密解密)
Dec 02 PHP
CodeIgniter表单验证方法实例详解
Mar 03 PHP
YII视图整合kindeditor扩展的方法
Jul 13 PHP
PHP中empty,isset,is_null用法和区别
Feb 19 PHP
PHP结合jquery ajax实现上传多张图片,并限制图片大小操作示例
Mar 01 PHP
php+ajax实现商品对比功能示例
Apr 13 PHP
php字符串过滤strip_tags()函数用法实例分析
Jun 24 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实现根据设备类型自动跳转相应页面的方法
2014/07/24 PHP
WordPress开发中自定义菜单的相关PHP函数使用简介
2016/01/05 PHP
PHP使用ActiveMQ实例
2018/02/05 PHP
laravel利用中间件做防非法登录和权限控制示例
2019/10/21 PHP
PHP使用openssl扩展实现加解密方法示例
2020/02/20 PHP
些很实用且必用的小脚本代码
2006/06/26 Javascript
比较全面的event对像在IE与FF中的区别 推荐
2009/09/21 Javascript
Extjs学习笔记之三 extjs form更多的表单项
2010/01/07 Javascript
一个可拖拽列宽表格实例演示
2012/11/26 Javascript
javascript中的事件代理初探
2014/03/08 Javascript
基于jQuery实现网页打印功能
2015/12/01 Javascript
js实现文字截断功能
2016/09/14 Javascript
mui上拉加载功能实例详解
2017/04/13 Javascript
详解用vue编写弹出框组件
2017/07/04 Javascript
BootStrap Table复选框默认选中功能的实现代码(从数据库获取到对应的状态进行判断是否为选中状态)
2017/07/11 Javascript
Vue.js 单页面多路由区域操作的实例详解
2017/07/17 Javascript
你点的 ES6一些小技巧,请查收
2018/04/25 Javascript
webstorm中vue语法的支持详解
2018/05/09 Javascript
微信小程序实现左右列表联动
2020/05/19 Javascript
Vue源码之关于vm.$delete()/Vue.use()内部原理详解
2019/05/01 Javascript
vue微信分享插件使用方法详解
2020/02/18 Javascript
JavaScript实现简单贪吃蛇效果
2020/03/09 Javascript
学习python的几条建议分享
2013/02/10 Python
python连接mysql数据库示例(做增删改操作)
2013/12/31 Python
老生常谈python之鸭子类和多态
2017/06/13 Python
Numpy数组array和矩阵matrix转换方法
2019/08/05 Python
TensorFlow梯度求解tf.gradients实例
2020/02/04 Python
python的链表基础知识点
2020/09/13 Python
python dir函数快速掌握用法技巧
2020/12/09 Python
房地产项目建议书
2014/03/12 职场文书
年终晚会主持词
2014/03/25 职场文书
工作推荐信范文
2014/05/10 职场文书
中秋晚会策划方案
2014/06/12 职场文书
不服从上级领导安排的检讨书
2014/09/14 职场文书
2014县政府领导班子对照检查材料思想汇报
2014/09/25 职场文书
2015年工会工作总结
2015/03/30 职场文书