使用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
打造计数器DIY三步曲(中)
Oct 09 PHP
php分页思路以及在ZF中的使用
May 30 PHP
一个简单且很好用的php分页类
Oct 26 PHP
完美实现wordpress禁止文章修订和自动保存的方法
Nov 03 PHP
php读取文件内容的方法汇总
Jan 24 PHP
php根据用户语言跳转相应网页
Nov 04 PHP
Thinkphp无限级分类代码
Nov 11 PHP
PHP函数nl2br()与自定义函数nl2p()换行用法分析
Apr 02 PHP
php实现计算百度地图坐标之间距离的方法
May 05 PHP
一个简单安全的PHP验证码类 附调用方法
Jun 24 PHP
PHP给源代码加密的几种方法汇总(推荐)
Feb 06 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 Undefined index报错的修复方法
2011/07/17 PHP
php获取YouTube视频信息的方法
2015/02/11 PHP
smarty中常用方法实例总结
2015/08/07 PHP
强制设为首页代码
2006/06/19 Javascript
js实现DIV的一些简单控制
2007/06/04 Javascript
各浏览器中querySelector和querySelectorAll的实现差异分析
2012/05/23 Javascript
js禁止document element对象选中文本实现代码
2013/03/21 Javascript
jQuery使用一个按钮控制图片的伸缩实现思路
2013/04/19 Javascript
JavaScript之IE的fireEvent方法详细解析
2013/11/20 Javascript
jQuery对Select的操作大集合(收藏)
2013/12/28 Javascript
javascript通过元素id和name直接取得元素的方法
2015/04/28 Javascript
window.onload与$(document).ready()的区别分析
2015/05/30 Javascript
JavaScipt选取文档元素的方法(推荐)
2016/08/05 Javascript
JS实现重新加载当前页面
2016/11/29 Javascript
js判断一个字符串是以某个字符串开头的简单实例
2016/12/27 Javascript
利用jQuery+localStorage实现一个简易的计时器示例代码
2017/12/25 jQuery
vue自定义全局组件(自定义插件)的用法
2018/01/30 Javascript
Vue完整项目构建(进阶篇)
2018/02/10 Javascript
解决layer.open弹出框不能获取input框的值为空的问题
2019/09/10 Javascript
Openlayers3实现车辆轨迹回放功能
2020/09/29 Javascript
[50:20]DOTA2上海特级锦标赛主赛事日 - 5 总决赛Liquid VS Secret第四局
2016/03/06 DOTA
win7上python2.7连接mysql数据库的方法
2017/01/14 Python
python购物车程序简单代码
2018/04/18 Python
Python 实现在文件中的每一行添加一个逗号
2018/04/29 Python
Python利用FFT进行简单滤波的实现
2020/02/26 Python
django实现将后台model对象转换成json对象并传递给前端jquery
2020/03/16 Python
Django 用户认证Auth组件的使用
2020/11/30 Python
CSS3使用多列制作瀑布流
2016/05/10 HTML / CSS
5个你不知道的HTML5的接口介绍
2013/08/07 HTML / CSS
实习心得体会
2014/01/02 职场文书
公司门卫管理制度
2014/02/01 职场文书
项目委托协议书(最新)
2014/09/13 职场文书
工作时间擅自离岗检讨书
2014/10/24 职场文书
2014年小学语文工作总结
2014/12/20 职场文书
关于召开会议的通知
2015/04/15 职场文书
Java由浅入深通关抽象类与接口(上篇)
2022/04/26 Java/Android