使用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 相关文章推荐
fleaphp下不确定的多条件查询的巧妙解决方法
Sep 11 PHP
PHP伪造referer实例代码
Sep 20 PHP
php下目前为目最全的CURL中文说明
Aug 01 PHP
解析thinkphp的左右值无限分类
Jun 20 PHP
Thinkphp中数据按分类嵌套循环实现方法
Oct 30 PHP
php用户登录之cookie信息安全分析
May 13 PHP
常用PHP数组排序函数归纳
Aug 08 PHP
PHP异常处理定义与使用方法分析
Jul 25 PHP
PHP+MySQL实现消息队列的方法分析
May 09 PHP
PHP集成环境XAMPP的安装与配置
Nov 13 PHP
PHP获取星期几的常用方法小结
Dec 18 PHP
PHP扩展类型及安装方式解析
Apr 27 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
ajax php 实现写入数据库
2009/09/02 PHP
PHP中常用的输出函数总结
2014/09/22 PHP
Yii框架在页面输出执行sql语句以方便调试的实现方法
2014/12/24 PHP
PHP+MariaDB数据库操作基本技巧备忘总结
2018/05/21 PHP
解决PhpStorm64不能启动的问题
2020/06/20 PHP
【消息提示组件】,兼容IE6/7&amp;&amp;FF2
2007/09/04 Javascript
javascript 文本框水印/占位符(watermark/placeholder)实现方法
2012/01/15 Javascript
js substr支持中文截取函数代码(中文是双字节)
2013/04/17 Javascript
深入学习JavaScript中的原型prototype
2015/08/13 Javascript
JS中生成随机数的用法及相关函数
2016/01/09 Javascript
bootstrap导航条实现代码
2016/12/28 Javascript
vuejs2.0子组件改变父组件的数据实例
2017/05/10 Javascript
如何优雅地在vue中添加权限控制示例详解
2019/03/07 Javascript
vue-cli 3 全局过滤器的实例代码详解
2019/06/03 Javascript
微信小程序基于高德地图查找位置并显示文字
2019/10/30 Javascript
Python实现的HTTP并发测试完整示例
2020/04/23 Python
Python正则表达式非贪婪、多行匹配功能示例
2017/08/08 Python
Python命令行解析模块详解
2018/02/01 Python
Python实现的生产者、消费者问题完整实例
2018/05/30 Python
python计算两个数的百分比方法
2018/06/29 Python
浅谈python的dataframe与series的创建方法
2018/11/12 Python
python浪漫表白源码
2019/04/05 Python
python requests更换代理适用于IP频率限制的方法
2019/08/21 Python
python飞机大战pygame碰撞检测实现方法分析
2019/12/17 Python
eDreams葡萄牙:全球最大的在线旅行社之一
2019/04/15 全球购物
C语言变量的命名规则都有哪些
2013/12/27 面试题
举例说明类变量和实例变量的区别
2016/06/30 面试题
大学生村官任职感言
2014/01/09 职场文书
家长会演讲稿范文
2014/01/10 职场文书
期末自我鉴定
2014/01/23 职场文书
应届毕业生简历自我评价
2014/01/31 职场文书
表扬信范文
2015/05/04 职场文书
山楂树之恋观后感
2015/06/11 职场文书
儿子满月酒致辞
2015/07/29 职场文书
浅谈mysql执行过程以及顺序
2021/05/12 MySQL
mysql在项目中怎么选事务隔离级别
2021/05/25 MySQL