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实现登陆验证码(类似条行码状)
Oct 09 PHP
php set_magic_quotes_runtime() 函数过时解决方法
Jul 08 PHP
php中hashtable实现示例分享
Feb 13 PHP
php使用array_rand()函数从数组中随机选择一个或多个元素
Apr 28 PHP
php数组使用规则分析
Feb 27 PHP
Thinkphp调用Image类生成缩略图的方法
Mar 07 PHP
再Docker中架设完整的WordPress站点全攻略
Jul 29 PHP
详解php的socket通信
Aug 11 PHP
php连接oracle数据库的方法(测试成功)
May 26 PHP
php获取开始与结束日期之间所有日期的方法
Nov 29 PHP
php版阿里云OSS图片上传类详解
Dec 01 PHP
php+croppic.js实现剪切上传图片功能
Aug 14 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面向对象中static静态属性和静态方法的调用
2015/02/08 PHP
PHP二分查找算法示例【递归与非递归方法】
2016/09/29 PHP
php中字符串和整数比较的操作方法
2019/06/06 PHP
使用jQuery同时控制四张图片的伸缩实现代码
2013/04/19 Javascript
基于编写jQuery的无缝滚动插件
2014/08/02 Javascript
Javascript检查图片大小不要让大图片撑破页面
2014/11/04 Javascript
jQuery实现的类似淘宝网站搜索框样式代码分享
2015/08/24 Javascript
jquery中cookie用法实例详解(获取,存储,删除等)
2016/01/04 Javascript
详解Bootstrap插件
2016/04/25 Javascript
将json转换成struts参数的方法
2016/11/08 Javascript
浅谈react+es6+webpack的基础配置
2017/08/09 Javascript
vue项目引入Iconfont图标库的教程图解
2018/10/24 Javascript
Node.js 进程平滑离场剖析小结
2019/01/24 Javascript
前端面试知识点目录一览
2019/04/15 Javascript
layui数据表格跨行自动合并的例子
2019/09/02 Javascript
vue项目强制清除页面缓存的例子
2019/11/06 Javascript
Node 模块原理与用法详解
2020/05/13 Javascript
[06:07]刀塔密之二:攻之吾命受之吾幸
2014/07/03 DOTA
[01:19:23]2018DOTA2亚洲邀请赛 4.5 淘汰赛 Mineski vs VG 第二场
2018/04/06 DOTA
基于python代码实现简易滤除数字的方法
2018/07/17 Python
Django+boostrap 美化admin后台的操作
2020/03/11 Python
python pandas.DataFrame.loc函数使用详解
2020/03/26 Python
python 批量下载bilibili视频的gui程序
2020/11/20 Python
详解基于canvas的视频遮罩插件
2018/01/04 HTML / CSS
耐克美国官网:Nike.com
2016/08/01 全球购物
Pamela Love官网:纽约设计师Pamela Love的精美、时尚和穿孔珠宝
2020/10/19 全球购物
Laravel中Kafka的使用详解
2021/03/24 PHP
毕业生自我鉴定范文
2013/11/08 职场文书
财务人员的自我评价范文
2014/03/03 职场文书
小学生作文评语
2014/04/18 职场文书
2014物价局群众路线对照检查材料思想汇报
2014/09/21 职场文书
重温经典:乔布斯在斯坦福大学的毕业演讲(双语)
2019/08/26 职场文书
Java SSM配置文件案例详解
2021/08/30 Java/Android
Python Pandas读取Excel日期数据的异常处理方法
2022/02/28 Python
python疲劳驾驶困倦低头检测功能的实现
2022/04/04 Python
解决MySQL Varchar 类型尾部空格的问题
2022/04/06 MySQL