本代码是从uchome的代码修改的
,是因为要解决uchome的效率而处理的
。 PHP实现的Mysql读写分离
主要特性:
简单的读写分离
一个主数据库
,可以添加更多的只读数据库
读写分离但不用担心某些特性不支持
缺点:同时连接两个数据库
英文比较烂,也写几个字吧
phpcodefor
mysqlread/writesplit
feature:
simplyrwsplit
onemaster,canaddmoreslaves
supportall
mysqlfeature
linktothemasterandslaveatthesametime
PHP代码:
mysql_rw_php.class.php
<?php
/****************************************
***mysql-rw-phpversion0.1@2009-4-16 ***codebyhqlulu#gmail.com
***http://www.aslibra.com
***http://code.google.com/p/mysql-rw-php/
***codemodifyfromclass_mysql.php(uchome)
****************************************/
classmysql_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;
functionmysql_rw_php(){
}
functionconnect($dbhost,$dbuser,$dbpw,$dbname='',$pconnect=0,$halt=TRUE){
if($pconnect){
if(!$this->link=@mysql_pconnect($dbhost,$dbuser,$dbpw)){
$halt&&$this->halt('CannotconnecttoMy
SQLserver');
}
}else{
if(!$this->link=@mysql_connect($dbhost,$dbuser,$dbpw)){
$halt&&$this->halt('CannotconnecttoMy
SQLserver');
}
}
//只读连接失败
if(!$this->link&&!$halt)returnfalse;
//未初始化rw时,第一个连接作为rw
if($this->link_rw==null)
$this->link_rw=$this->link;
if($this->version()>'4.1'){
if($this->charset){
@mysql_query("SETcharacter_set_connection=$this->charset,character_set_results=$this->charset,character_set_client=binary",$this->link);
}
if($this->version()>'5.0.1'){
@mysql_query("SETsql_mode=''",$this->link);
}
}
if($dbname){
$this->select_db($dbname);
}
}
//连接一个只读的mysql数据库
functionconnect_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"linkrosussess!<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"linkrofailed!<br>";
$this->link=&$this->link_rw;
}
}
//设置一系列只读数据库并且连接其中一个
functionset_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']);
}
}
functionselect_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);
}
functionfetch_array($query,$result_type=MYSQL_ASSOC){
returnmysql_fetch_array($query,$result_type);
}
functionfetch_one_array($sql,$type=''){
$qr=$this->query($sql,$type);
return$this->fetch_array($qr);
}
functionquery($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('MySQLQueryError',$sql);
}
$this->querynum++;
return$query;
}
functionaffected_rows(){
returnmysql_affected_rows($this->link);
}
functionerror(){
return(($this->link)?mysql_error($this->link):mysql_error());
}
functionerrno(){
returnintval(($this->link)?mysql_errno($this->link):mysql_errno());
}
functionresult($query,$row){
$query=@mysql_result($query,$row);
return$query;
}
functionnum_rows($query){
$query=mysql_num_rows($query);
return$query;
}
functionnum_fields($query){
returnmysql_num_fields($query);
}
functionfree_result($query){
returnmysql_free_result($query);
}
functioninsert_id(){
return($id=mysql_insert_id($this->link))>=0?$id:$this->result($this->query("SELECTlast_insert_id()"),0);
}
functionfetch_row($query){
$query=mysql_fetch_row($query);
return$query;
}
functionfetch_fields($query){
returnmysql_fetch_field($query);
}
functionversion(){
returnmysql_get_server_info($this->link);
}
functionclose(){
returnmysql_close($this->link);
}
functionhalt($message='',$sql=''){
$dberror=$this->error();
$dberrno=$this->errno();
echo"<divstyle="position:absolute;font-size:11px;font-family:verdana,arial;background:#EBEBEB;padding:0.5em;">
<b>MySQLError</b><br>
<b>Message</b>:$message<br>
<b>SQL</b>:$sql<br>
<b>Error</b>:$dberror<br>
<b>Errno.</b>:$dberrno<br>
</div>";
exit();
}
}
?>
example.php
<?php
/****************************************
***mysql-rw-phpversion0.1@2009-4-16 ***codebyhqlulu#gmail.com
***http://www.aslibra.com
***http://code.google.com/p/mysql-rw-php/
***codemodifyfromclass_mysql.php(uchome)
****************************************/
require_once('mysql_rw_php.class.php');
//rwinfo
$db_rw=array(
'dbhost'=>'www.aslibra.com',
'dbuser'=>'aslibra',
'dbpw'=>'www.aslibra.com',
'dbname'=>'test'
);
$db_ro=array(
array(
'dbhost'=>'www.aslibra.com:4306',
'dbuser'=>'aslibra',
'dbpw'=>'www.aslibra.com'
)
);
$DB=newmysql_rw_php;
//connectMaster
$DB->connect($db_rw[dbhost],$db_rw[dbuser],$db_rw[dbpw],$db_rw[dbname]);
//Method1:connectoneserver
$DB->connect_ro($db_ro[0][dbhost],$db_ro[0][dbuser],$db_ro[0][dbpw]);
//Method2:connectoneserverfromalistbyrand
$DB->set_ro_list($db_ro);
//sendtorw
$sql="insertintoaseta='test'";
$DB->query($sql);
//sendtoro
$sql="select*froma";
$qr=$DB->query($sql);
while($row=$DB->fetch_array($qr)){
echo$row[a];
}
?>
相关项目:
MySQL_Proxy
mysql_proxy好像还没有建议应用在生产环境,可能还有部分没解决的bug
mysql-master-master
需要perl环境支持,可以试试,说是在生产环境应用的
amoeba变形虫
性能听说比mysql-proxy好,但部分语句可能不支持,这个需要考虑一下是否适用了