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 相关文章推荐
第十五节--Zend引擎的发展
Nov 16 PHP
从Web查询数据库之PHP与MySQL篇
Sep 25 PHP
从康盛产品(discuz)提取出来的模板类
Jun 28 PHP
整理的一些实用WordPress后台MySQL操作命令
Jan 07 PHP
PHP中ob_start函数的使用说明
Nov 11 PHP
php中session退出登陆问题
Feb 27 PHP
PHP图片裁剪函数(保持图像不变形)
May 04 PHP
PHP实现模仿socket请求返回页面的方法
Nov 04 PHP
微信支付开发发货通知实例
Jul 12 PHP
基于php实现的php代码加密解密类完整实例
Oct 12 PHP
老生常谈php 正则中的i,m,s,x,e分别表示什么
Mar 02 PHP
THINKPHP3.2使用soap连接webservice的解决方法
Dec 13 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
动画 《Pokemon Sword·Shield》系列WEB动画《薄明之翼》第2话声优阵容公开!
2020/03/06 日漫
PHP 强制性文件下载功能的函数代码(任意文件格式)
2010/05/26 PHP
PHP Session 变量的使用方法详解与实例代码
2013/09/11 PHP
PHP+Ajax实现验证码的实时验证
2016/07/20 PHP
php设计模式之策略模式实例分析【星际争霸游戏案例】
2020/03/26 PHP
JavaScript delete 属性的使用
2009/10/08 Javascript
js去除重复字符串两种实现方法
2013/01/09 Javascript
js判断某个方法是否存在实例代码
2015/01/10 Javascript
使用AngularJS编写较为优美的JavaScript代码指南
2015/06/19 Javascript
表单验证插件Validation应用的实例讲解
2015/10/10 Javascript
Angular.js如何从PHP读取后台数据
2016/03/24 Javascript
微信小程序 动态的设置图片的高度和宽度详解及实例代码
2017/02/24 Javascript
关于TypeScript中import JSON的正确姿势详解
2017/07/25 Javascript
浅谈ECMAScript6新特性之let、const
2017/08/02 Javascript
Angularjs中的$apply及优化使用详解
2018/07/02 Javascript
js canvas实现二维码和图片合成的海报
2020/11/19 Javascript
bootstrap table实现合并单元格效果
2018/12/24 Javascript
JS中的变量作用域(console版)
2020/07/18 Javascript
tensorflow入门之训练简单的神经网络方法
2018/02/26 Python
python引入不同文件夹下的自定义模块方法
2018/10/27 Python
Django框架实现的普通登录案例【使用POST方法】
2019/05/15 Python
Django Rest framework三种分页方式详解
2019/07/26 Python
python中几种自动微分库解析
2019/08/29 Python
python+django+rest框架配置创建方法
2019/08/31 Python
Python操作MySQL数据库实例详解【安装、连接、增删改查等】
2020/01/17 Python
使用jupyter notebook运行python和R的步骤
2020/08/13 Python
Python3.9最新版下载与安装图文教程详解(Windows系统为例)
2020/11/28 Python
贝玲妃美国官方网站:Benefit美国
2016/08/28 全球购物
Ibatis如何调用存储过程
2015/05/15 面试题
体育教育毕业生自荐信
2013/11/21 职场文书
入党申请人的自我鉴定
2013/12/01 职场文书
珍惜时间演讲稿
2014/05/14 职场文书
奥运会口号
2014/06/13 职场文书
消防宣传标语大全
2015/08/03 职场文书
爱护环境建议书
2015/09/14 职场文书
初二数学教学反思
2016/02/17 职场文书