使用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 相关文章推荐
隐藏X-Space个人空间下方版权方法隐藏X-Space个人空间标题隐藏X-Space个人空间管理版权方法
Feb 22 PHP
php 远程图片保存到本地的函数类
Dec 08 PHP
PHP 危险函数解释 分析
Apr 22 PHP
thinkphp 多表 事务详解
Jun 17 PHP
php递归获取目录内文件(包含子目录)封装类分享
Dec 25 PHP
php使用数组填充下拉列表框的方法
Mar 31 PHP
全面解析PHP操作Memcache基本函数
Jul 14 PHP
php 计算两个时间相差的天数、小时数、分钟数、秒数详解及实例代码
Nov 09 PHP
利用PHP访问MySql数据库的逻辑操作以及增删改查的实例讲解
Aug 30 PHP
Smarty缓存机制实例详解【三种缓存方式】
Jul 20 PHP
PHP 代码简洁之道(小结)
Oct 16 PHP
PHP文件操作简单介绍及函数汇总
Dec 11 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/06/14 PHP
PHP curl 并发最佳实践代码分享
2012/09/05 PHP
Zend Framework实现Zend_View集成Smarty模板系统的方法
2016/03/05 PHP
php微信开发之自定义菜单实现
2016/11/18 PHP
javascript document.referrer 用法
2009/04/30 Javascript
firefox插件Firebug的使用教程
2010/01/02 Javascript
判断js中各种数据的类型方法之typeof与0bject.prototype.toString讲解
2013/11/07 Javascript
JS实现日期加减的方法
2013/11/29 Javascript
js 跳出页面的frameset框架示例介绍
2013/12/23 Javascript
JQuery插件iScroll实现下拉刷新,滚动翻页特效
2014/06/22 Javascript
JavaScript组合拼接字符串的效率对比测试
2014/11/06 Javascript
JavaScript将字符串转换为整数的方法
2015/04/14 Javascript
jQuery常用且重要方法汇总
2015/07/13 Javascript
Javascript中的数组常用方法解析
2016/06/17 Javascript
Bootstrap select实现下拉框多选效果
2016/12/23 Javascript
vue-router路由简单案例介绍
2017/02/21 Javascript
详解jquery选择器的原理
2017/08/01 jQuery
浅析微信扫码登录原理(小结)
2018/10/29 Javascript
详解webpack打包后如何调试的方法步骤
2018/11/07 Javascript
vue滚动固定顶部及修改样式的实例代码
2019/05/30 Javascript
微信小程序tabBar设置实例解析
2019/11/14 Javascript
vue项目中自定义video视频控制条的实现代码
2020/04/26 Javascript
Node.JS如何实现JWT原理
2020/09/18 Javascript
[02:25]专访DOTA2负责人Erik 国际邀请赛暂不会离开西雅
2014/07/21 DOTA
[01:10:24]DOTA2-DPC中国联赛 正赛 VG vs Aster BO3 第一场 2月28日
2021/03/11 DOTA
Python selenium 三种等待方式解读
2016/09/15 Python
Python按行读取文件的实现方法【小文件和大文件读取】
2016/09/19 Python
python中Pycharm 输出中文或打印中文乱码现象的解决办法
2017/06/16 Python
Python调用系统底层API播放wav文件的方法
2017/08/11 Python
Python面向对象程序设计之类和对象、实例变量、类变量用法分析
2020/03/23 Python
详解python的xlwings库读写excel操作总结
2021/02/26 Python
20佳惊艳的HTML5应用程序示例分享
2011/05/03 HTML / CSS
AmazeUI 面板的实现示例
2020/08/17 HTML / CSS
关于递归的一道.NET面试题
2013/05/12 面试题
市场策划求职信
2014/08/07 职场文书
python 模块重载的五种方法
2021/04/24 Python