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和ACCESS写聊天室(七)
Oct 09 PHP
开发大型 PHP 项目的方法
Jan 02 PHP
pdo中使用参数化查询sql
Aug 11 PHP
分享一个PHP数据流应用的简单例子
Jun 01 PHP
深入探讨:PHP使用数据库永久连接方式操作MySQL的是与非
Jun 05 PHP
探讨:array2xml和xml2array以及xml与array的互相转化
Jun 24 PHP
PHP实现获取图片颜色值的方法
Jul 11 PHP
php连接oracle数据库及查询数据的方法
Dec 29 PHP
php中解析带中文字符的url函数分享
Jan 20 PHP
php官方微信接口大全(微信支付、微信红包、微信摇一摇、微信小店)
Dec 21 PHP
yii2局部关闭(开启)csrf的验证的实例代码
Jul 10 PHP
YII分模块加载路由的实现方法
Oct 01 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
Thinkphp实现短信验证注册功能
2016/10/18 PHP
PHP实现截取中文字符串不出现?号的解决方法
2016/12/29 PHP
php基于dom实现读取图书xml格式数据的方法
2017/02/03 PHP
PJBlog插件 防刷新的在线播放器
2006/10/25 Javascript
用JavaScript玩转游戏物理(一)运动学模拟与粒子系统
2010/06/19 Javascript
JavaScript与Image加载事件(onload)、加载状态(complete)
2011/02/14 Javascript
JavaScript版DateAdd和DateDiff函数代码
2012/03/01 Javascript
基于jQuery实现图片的前进与后退功能
2013/04/24 Javascript
利用js读取动态网站从服务器端返回的数据
2014/02/10 Javascript
Js制作点击输入框时默认文字消失的效果
2015/09/05 Javascript
jquery easyui dataGrid动态改变排序字段名的方法
2017/03/02 Javascript
JS中利用localStorage防止页面动态添加数据刷新后数据丢失
2017/03/10 Javascript
Bootstrap Table快速完美搭建后台管理系统
2017/09/20 Javascript
angularjs实现分页和搜索功能
2018/01/03 Javascript
AngularJS使用Filter自定义过滤器控制ng-repeat去除重复功能示例
2018/04/21 Javascript
vue项目前端埋点的实现
2019/03/06 Javascript
原生js实现照片墙效果
2020/10/13 Javascript
python获取标准北京时间的方法
2015/03/24 Python
Python中函数参数设置及使用的学习笔记
2016/05/03 Python
Atom的python插件和常用插件说明
2018/07/08 Python
Python3.5运算符操作实例详解
2019/04/25 Python
Django模型序列化返回自然主键值示例代码
2019/06/12 Python
Python turtle库的画笔控制说明
2020/06/28 Python
python获取天气接口给指定微信好友发天气预报
2020/12/28 Python
详解html2canvas截图不能截取圆角图片的解决方案
2018/01/30 HTML / CSS
Ariat官网:美国马靴和服装品牌
2019/12/16 全球购物
澳大利亚领先的女性运动服品牌:Lorna Jane
2020/06/19 全球购物
期末总结的个人自我评价
2013/11/02 职场文书
大学生会计职业生涯规划范文
2014/02/28 职场文书
电气工程自动化求职信
2014/03/14 职场文书
2014年两会学习心得范例
2014/03/17 职场文书
工厂门卫岗位职责范本
2014/04/04 职场文书
学校标语大全
2014/06/19 职场文书
加入学生会自荐书
2015/03/05 职场文书
心得体会格式及范文
2016/01/25 职场文书
在NumPy中深拷贝和浅拷贝相关操作的定义和背后的原理
2022/04/14 Python