使用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
dedecms防止FCK乱格式化你的代码的修改方法
Mar 17 PHP
php minixml详解
Jul 19 PHP
在Windows下编译适用于PHP 5.2.12及5.2.13的eAccelerator.dll(附下载)
May 04 PHP
php feof用来识别文件末尾字符的方法
Aug 01 PHP
php设计模式 Proxy (代理模式)
Jun 26 PHP
php从字符串创建函数的方法
Mar 16 PHP
详解WordPress开发中过滤属性以及Sql语句的函数使用
Dec 25 PHP
PHP封装函数实现生成随机的字符串验证码
Jan 24 PHP
PHP基于pdo的数据库操作类【可支持mysql、sqlserver及oracle】
May 21 PHP
详解PHP神奇又有用的Trait
Mar 25 PHP
PHP中遍历数组的三种常用方法实例分析
Jun 24 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+jquery编码方面的一些心得(utf-8 gb2312)
2010/10/12 PHP
PHP 中检查或过滤IP地址的实现代码
2011/11/27 PHP
Erlang的运算符(比较运算符,数值运算符,移位运算符,逻辑运算符)
2012/07/23 PHP
php循环创建目录示例分享(php创建多级目录)
2014/03/04 PHP
PHP 微信支付类 demo
2015/11/30 PHP
解读PHP中上传文件的处理问题
2016/05/29 PHP
PHP Swoole异步读取、写入文件操作示例
2019/10/24 PHP
javascript中的对象和数组的应用技巧
2007/01/07 Javascript
Javascript与flash交互通信基础教程
2008/08/07 Javascript
很全的显示阴历(农历)日期的js代码
2009/01/01 Javascript
ie支持function.bind()方法实现代码
2012/12/27 Javascript
JS弹出层遮罩,隐藏背景页面滚动条细节优化分析
2016/04/29 Javascript
vue.js开发实现全局调用的MessageBox组件实例代码
2017/11/22 Javascript
jQuery实现动态显示select下拉列表数据的方法
2018/02/05 jQuery
Javascript实现异步编程的过程
2018/06/18 Javascript
JavaScript去掉数组重复项的方法分析【测试可用】
2018/07/19 Javascript
在iFrame子页面里实现模态框的方法
2018/08/17 Javascript
vue全局使用axios的方法实例详解
2018/11/22 Javascript
javascript的this关键字详解
2019/05/20 Javascript
小程序实现横向滑动日历效果
2019/10/21 Javascript
webpack.DefinePlugin与cross-env区别详解
2020/02/23 Javascript
Vue父子组件传值的一些坑
2020/09/16 Javascript
python 控制语句
2011/11/03 Python
使用Python实现BT种子和磁力链接的相互转换
2015/11/09 Python
python使用opencv读取图片的实例
2017/08/17 Python
Python实现点阵字体读取与转换的方法
2019/01/29 Python
如何分离django中的媒体、静态文件和网页
2019/11/12 Python
CSS3弹性盒模型flex box快速入门心得(必看篇)
2016/05/24 HTML / CSS
联想中国官方商城:Lenovo China
2017/10/18 全球购物
39美元购买一副眼镜或太阳镜:39DollarGlasses.com
2018/06/17 全球购物
德国黑胶唱片、街头服装及运动鞋网上商店:HHV
2018/08/24 全球购物
swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上
2013/07/06 面试题
阳光体育活动方案
2014/02/16 职场文书
医德考评自我评价
2014/09/14 职场文书
详解Redis基本命令与使用场景
2021/06/01 Redis
彻底卸载VMware虚拟机的超详细步骤记录
2022/07/15 Servers