使用PHP实现Mysql读写分离


Posted in PHP onJune 28, 2013

本代码是从uchome的代码修改的,是因为要解决uchome的效率而处理的。这个思维其实很久就有了,只是一直没有去做,相信也有人有同样的想法,如果有类似的,那真的希望提出相关的建议。

封装的方式比较简单,增加了只读数据库连接的接口扩展,不使用只读数据库也不影响原代码使用。有待以后不断完善。。
为了方便,试试建立了google的一个项目:
http://code.google.com/p/mysql-rw-php/
希望给有需要的朋友带来帮助。

PHP实现的Mysql读写分离
主要特性:
1.简单的读写分离
2.一个主数据库,可以添加更多的只读数据库
3.读写分离但不用担心某些特性不支持
4.缺点:同时连接两个数据库
英文比较烂,也写几个字吧
php code for mysql read/write split
feature:
simply rw split
one master,can add more slaves
support all mysql feature
link to the master and slave at the same time
PHP代码:
mysql_rw_php.class.php

<?php
/****************************************
*** mysql-rw-php version 0.1 
*** code by hqlulu#gmail.com
*** http://www.aslibra.com
*** http://code.google.com/p/mysql-rw-php/
*** code modify from class_mysql.php (uchome)
****************************************/
class mysql_rw_php {
  //查询个数
  var $querynum = 0;
  //当前操作的数据库连接
  var $link = null;
  //字符集
  var $charset;
  //当前数据库
  var $cur_db = '';
  //是否存在有效的只读数据库连接
  var $ro_exist = false;
  //只读数据库连接
  var $link_ro = null;
  //读写数据库连接
  var $link_rw = null;
  function mysql_rw_php(){
  }
  function connect($dbhost, $dbuser, $dbpw, $dbname = '', $pconnect = 0, $halt = TRUE) {
    if($pconnect) {
      if(!$this->link = @mysql_pconnect($dbhost, $dbuser, $dbpw)) {
        $halt && $this->halt('Can not connect to MySQL server');
      }
    } else {
      if(!$this->link = @mysql_connect($dbhost, $dbuser, $dbpw)) {
        $halt && $this->halt('Can not connect to MySQL server');
      }
    }    //只读连接失败
    if(!$this->link && !$halt) return false;
    //未初始化rw时,第一个连接作为rw
    if($this->link_rw == null)
      $this->link_rw = $this->link;
    if($this->version() > '4.1') {
      if($this->charset) {
        @mysql_query("SET character_set_connection=$this->charset, character_set_results=$this->charset, character_set_client=binary", $this->link);
      }
      if($this->version() > '5.0.1') {
        @mysql_query("SET sql_mode=''", $this->link);
      }
    }
    if($dbname) {
      $this->select_db($dbname);
    }
  }
  //连接一个只读的mysql数据库
  function connect_ro($dbhost, $dbuser, $dbpw, $dbname = '', $pconnect = 0){
    if($this->link_rw == null)
      $this->link_rw = $this->link;
    $this->link = null;
    //不产生halt错误
    $this->connect($dbhost, $dbuser, $dbpw, $dbname, $pconnect, false);
    if($this->link){
      //连接成功
      //echo "link ro sussess!<br>";
      $this->ro_exist = true;
      $this->link_ro = $this->link;
      if($this->cur_db){
        //如果已经选择过数据库则需要操作一次
        @mysql_select_db($this->cur_db, $this->link_ro);
      }
    }else{
      //连接失败
      //echo "link ro failed!<br>";
      $this->link = &$this->link_rw;
    }
  }
  //设置一系列只读数据库并且连接其中一个
  function set_ro_list($ro_list){
    if(is_array($ro_list)){
      //随机选择其中一个
      $link_ro = $ro_list[array_rand($ro_list)];
      $this->connect_ro($link_ro['dbhost'], $link_ro['dbuser'], $link_ro['dbpw']);
    }
  }
  function select_db($dbname) {
    //同时操作两个数据库连接
    $this->cur_db = $dbname;
    if($this->ro_exist){
      @mysql_select_db($dbname, $this->link_ro);
    }
    return @mysql_select_db($dbname, $this->link_rw);
  }
  function fetch_array($query, $result_type = MYSQL_ASSOC) {
    return mysql_fetch_array($query, $result_type);
  }
  function fetch_one_array($sql, $type = '') {
    $qr = $this->query($sql, $type);
    return $this->fetch_array($qr);
  }
  function query($sql, $type = '') {
    $this->link = &$this->link_rw;
    //判断是否select语句
    if($this->ro_exist && preg_match ("/^(\s*)select/i", $sql)){
      $this->link = &$this->link_ro;
    }
    $func = $type == 'UNBUFFERED' && @function_exists('mysql_unbuffered_query') ?
      'mysql_unbuffered_query' : 'mysql_query';
    if(!($query = $func($sql, $this->link)) && $type != 'SILENT') {
      $this->halt('MySQL Query Error', $sql);
    }
    $this->querynum++;
    return $query;
  }
  function affected_rows() {
    return mysql_affected_rows($this->link);
  }
  function error() {
    return (($this->link) ? mysql_error($this->link) : mysql_error());
  }
  function errno() {
    return intval(($this->link) ? mysql_errno($this->link) : mysql_errno());
  }
  function result($query, $row) {
    $query = @mysql_result($query, $row);
    return $query;
  }
  function num_rows($query) {
    $query = mysql_num_rows($query);
    return $query;
  }
  function num_fields($query) {
    return mysql_num_fields($query);
  }
  function free_result($query) {
    return mysql_free_result($query);
  }
  function insert_id() {
    return ($id = mysql_insert_id($this->link)) >= 0 ? $id : $this->result($this->query("SELECT last_insert_id()"), 0);
  }
  function fetch_row($query) {
    $query = mysql_fetch_row($query);
    return $query;
  }
  function fetch_fields($query) {
    return mysql_fetch_field($query);
  }
  function version() {
    return mysql_get_server_info($this->link);
  }
  function close() {
    return mysql_close($this->link);
  }
  function halt($message = '', $sql = '') {
    $dberror = $this->error();
    $dberrno = $this->errno();
    echo "<div style=\"position:absolute;font-size:11px;font-family:verdana,arial;background:#EBEBEB;padding:0.5em;\">
        <b>MySQL Error</b><br>
        <b>Message</b>: $message<br>
        <b>SQL</b>: $sql<br>
        <b>Error</b>: $dberror<br>
        <b>Errno.</b>: $dberrno<br>
        </div>";
    exit();
  }
}
?>
PHP 相关文章推荐
PHP实现网上点歌(二)
Oct 09 PHP
从C/C++迁移到PHP——判断字符类型的函数
Oct 09 PHP
SSI指令
Nov 25 PHP
一些PHP写的小东西
Dec 06 PHP
《PHP边学边教》(02.Apache+PHP环境配置――下篇)
Dec 13 PHP
一篇不错的PHP基础学习笔记
Mar 18 PHP
php 显示指定路径下的图片
Oct 29 PHP
PHP 图片上传实现代码 带详细注释
Apr 29 PHP
php获取本地图片文件并生成xml文件输出具体思路
Apr 27 PHP
phpmailer中文乱码问题的解决方法
Apr 22 PHP
php数组使用规则分析
Feb 27 PHP
PHP7创建销毁session的实例方法
Feb 03 PHP
win7下memCache的安装过程(具体操作步骤)
Jun 28 #PHP
浅析memcache启动以及telnet命令详解
Jun 28 #PHP
浅析HTTP消息头网页缓存控制以及header常用指令介绍
Jun 28 #PHP
深入apache配置文件httpd.conf的部分参数说明
Jun 28 #PHP
浅析php变量修饰符static的使用
Jun 28 #PHP
解析php如何将日志写进syslog
Jun 28 #PHP
解析PHP中VC6 X86和VC9 X86的区别及 Non Thread Safe的意思
Jun 28 #PHP
You might like
PHP 抓取网页图片并且另存为的实现代码
2010/03/24 PHP
zf框架的session会话周期及次数限制使用示例
2014/03/13 PHP
php模拟post提交请求调用接口示例解析
2020/08/07 PHP
javascript Array数组对象的扩展函数代码
2010/05/22 Javascript
15款优秀的jQuery导航菜单插件分享
2011/07/19 Javascript
jQuery EasyUI API 中文文档 可调整尺寸
2011/09/29 Javascript
addEventListener()第三个参数useCapture (Boolean)详细解析
2013/11/07 Javascript
Ajax请求在数据量大的时候出现超时的解决方法
2014/02/27 Javascript
js实现类似jquery里animate动画效果的方法
2015/04/10 Javascript
ES6中如何使用Set和WeakSet
2016/03/10 Javascript
Bootstrap教程JS插件弹出框学习笔记分享
2016/05/17 Javascript
通过jquery-ui中的sortable来实现拖拽排序的简单实例
2016/05/24 Javascript
javascript显示系统当前时间代码
2016/12/29 Javascript
详解angularjs 学习之 scope作用域
2018/01/15 Javascript
javascript数组拍平方法总结
2018/01/20 Javascript
vue2.x 通过后端接口代理,获取qq音乐api的数据示例
2019/10/30 Javascript
分享Angular http interceptors 拦截器使用(推荐)
2019/11/10 Javascript
JS实现音乐钢琴特效
2020/01/06 Javascript
Vue是怎么渲染template内的标签内容的
2020/06/05 Javascript
[00:32]2018DOTA2亚洲邀请赛Newbee出场
2018/04/03 DOTA
Python实现控制台进度条功能
2016/01/04 Python
对TensorFlow中的variables_to_restore函数详解
2018/07/30 Python
解决python测试opencv时imread导致的错误问题
2019/01/26 Python
利用Python脚本批量生成SQL语句
2020/03/04 Python
django template实现定义临时变量,自定义赋值、自增实例
2020/07/12 Python
CSS教程:CSS3圆角属性
2009/04/02 HTML / CSS
html5 div布局与table布局详解
2016/11/16 HTML / CSS
Stuart Weitzman美国官网:美国奢华鞋履品牌
2016/08/18 全球购物
Athleta官网:购买女士瑜伽服、技术运动服和休闲运动服
2020/11/12 全球购物
电脑专业个人求职信范文
2014/02/04 职场文书
大学毕业感言一句话
2014/02/06 职场文书
护士节活动总结
2014/08/29 职场文书
公证处委托书
2015/01/28 职场文书
单位推荐信范文
2015/03/27 职场文书
pytorch中[..., 0]的用法说明
2021/05/20 Python
Win11 BitLocker 驱动器加密
2022/04/19 数码科技