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 开发环境配置(Zend Studio)
Apr 28 PHP
POSIX 风格和兼容 Perl 风格两种正则表达式主要函数的类比(preg_match, preg_replace, ereg, ereg_replace)
Oct 12 PHP
关于mysql字符集设置了character_set_client=binary 在gbk情况下会出现表描述是乱码的情况
Jan 06 PHP
解析用PHP读写音频文件信息的详解(支持WMA和MP3)
May 10 PHP
浅谈discuz密码加密的方式
May 22 PHP
PHP实现设计模式中的抽象工厂模式详解
Oct 11 PHP
使用PHPExcel操作Excel用法实例分析
Mar 26 PHP
php实现生成验证码实例分享
Apr 10 PHP
浅析PHP开发规范
Feb 05 PHP
thinkPHP事务操作简单案例分析
Oct 17 PHP
PHP设计模式之数据访问对象模式(DAO)原理与用法实例分析
Dec 12 PHP
PHP 实现链式操作
Mar 09 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+SQL 注入攻击的技术实现以及预防办法
2011/01/27 PHP
PHP实现的sqlite数据库连接类
2014/12/12 PHP
在Debian系统下配置LNMP的教程
2015/07/09 PHP
PHP中的self关键字详解
2019/06/23 PHP
将string解析为json的几种方式小结
2010/11/11 Javascript
基于jquery的3d效果实现代码
2011/03/23 Javascript
js Calender控件使用详解
2015/01/05 Javascript
JS验证IP,子网掩码,网关和MAC的方法
2015/07/02 Javascript
JS+CSS实现简易的滑动门效果代码
2015/09/24 Javascript
轻松实现js图片预览功能
2016/01/18 Javascript
模仿password输入框的实现代码
2016/06/07 Javascript
浅谈angular懒加载的一些坑
2016/08/20 Javascript
JavaScript 函数模式详解及示例
2016/09/07 Javascript
BootStrap中的表单大全
2016/09/07 Javascript
JS中使用react-tooltip插件实现鼠标悬浮显示框
2019/05/15 Javascript
angular使用md5,CryptoJS des加密的方法
2019/06/03 Javascript
详解BootStrap表单验证中重置BootStrap-select验证提示不清除的坑
2019/09/17 Javascript
小程序采集录音并上传到后台
2019/11/22 Javascript
国内常用的js类库大全(CDN公共库)
2020/06/24 Javascript
超详细小程序定位地图模块全系列开发教学
2020/11/24 Javascript
[02:25]DOTA2英雄基础教程 熊战士
2014/01/03 DOTA
Python实现二分法算法实例
2015/02/02 Python
Python多线程编程(五):死锁的形成
2015/04/05 Python
python绘制中国大陆人口热力图
2018/11/07 Python
程序员写Python时的5个坏习惯,你有几条?
2018/11/26 Python
详解css3 object-fit属性
2018/07/27 HTML / CSS
美国知名的女性服饰品牌:LOFT(洛芙特)
2016/08/05 全球购物
巴西电子、家电、智能手机购物网站:Girafa
2019/06/04 全球购物
利物浦足球俱乐部官方商店(美国):Liverpool FC US
2019/10/09 全球购物
自我鉴定模板
2013/10/29 职场文书
《三峡》教学反思
2014/03/01 职场文书
仓库主管岗位职责
2014/03/02 职场文书
房屋租赁意向书
2014/04/01 职场文书
5.12护士节演讲稿
2014/04/30 职场文书
付款委托书范本
2014/10/05 职场文书
债务追讨授权委托书范本
2014/10/16 职场文书