/** * Mysql代理类 支持Master/Slave 读写分离 客户端不需担忧连Master/Slave 本类自动代理完成 * * @author 小黑米 * @package Core.DB * @version 1.0 beat * @copyright 2008-5-8 * @todo 下一步准备开发支持多memcache的代理 */ /* 配置: $dns = array( array(//第一个为主库 "host"=>"localhost", "user"=>"root", "pwd"=>"123456", "port"=>3306, "db"=>"phpexp", ), //剩下的都是从库 array( "host"=>"localhost", "user"=>"root", "pwd"=>"123456", "port"=>3306, "db"=>"phpexp", ), ); 执行方法: Mysql::getInstance()->fetchResult("select * from frame_role"); Mysql::getInstance()->query("update frame_role set name=test limit 1"); SQL记录追踪: array(2) { ["times"] => int(2) ["sqls"] => array(2) { [0] => array(2) { ["sql"] => string(24) "select * from frame_role" ["type"] => string(5) "slave" } [1] => array(2) { ["sql"] => string(39) "update frame_role set name=test limit 1" ["type"] => string(6) "master" } } } 执行结果: array(2) { [0] => array(4) { ["id"] => string(1) "1" ["rname"] => string(7) "tourisa" ["rmark"] => string(6) "游客" ["rprev"] => string(6) "a:0:{}" } [1] => array(4) { ["id"] => string(1) "2" ["rname"] => string(7) "tourise" ["rmark"] => string(7) "游客1" ["rprev"] => string(6) "a:0:{}" } } */ class Mysql{ /** * 单例模式 * * @var resource */ private static $instance = null; /** * Master 单例 * * @var resource */ private static $master = null; /** * Slave 单例 * * @var resource */ private static $slave = null; /** * 数据库执行记录 * * @var array */ public static $querys = array("times"=>0,"sqls"=>array()); private $_tmpRes = null; /** * 获取单例 * * @return resource */ public static function getInstance(){ if(!self::$instance) { self::$instance = new Mysql(); } return self::$instance; } /** * 构造函数 保留 * */ private function __construct(){} /** * 取记录 并根据自动hash结果集 * * @param string $sql * @param string $hashBy * @return array */ public function fetchResult($sql,$hashBy=null){ $return = array(); $this->query($sql); if(!$this->_tmpRes) httpError("handler500","SQL:{$sql} 执行失败"); if(!$hashBy) { while ($res = mysql_fetch_assoc($this->_tmpRes)) { $return[] = $res; } } else { while ($res = mysql_fetch_assoc($this->_tmpRes)) { $return[$res[$hashBy]] = $res; } } return $return; } /** * 执行指令 * * @param string $sql * @return resource */ public function query($sql){ self::$querys['times']++; $conn = $this->_checkSql($sql); self::$querys['sqls'][] = array("sql"=>$sql,"type"=>$conn['type']); // d(mysql_query($sql,$this->conn) or die(mysql_error()),false); $this->_tmpRes = mysql_query($sql,$conn['conn']) or httpError("handler500",mysql_error()); } /** * 分析SQL语句,自动分配到主库,从库 * * @param string $sql * @return resource */ private function _checkSql($sql){ global $dns; $_n = count($dns); if(count($dns)===1) {//主从同样 return $this->_getHelper($dns[0],"master"); } else { $type = substr($sql,0,strpos($sql," ")); if ($type === 'select') {//读从库 if($_n=2) { $ddns = $dns[1]; } else {//随即取一个从库 $ddns = $dns[mt_rand(1,$_n-1)]; } return $this->_getHelper($ddns); } else {//更新主库 return $this->_getHelper($dns[0],"master"); } } } /** * 主从库助手函数 * * @param array $dns * @param string $type Slave/Master * @return resource */ private function _getHelper($dns,$type="slave"){ if(!self::$$type) { self::$$type = new Helper($dns); } return array("conn"=>self::$$type->getConn(),"type"=>$type); } /** * 影响记录数 * * @param string $sql * @return array */ public function getAffectRows(){ return mysql_affected_rows(); } /** * 最后插入的ID * * @param string $sql * @return array */ public function getLastInsertId(){ return mysql_insert_id(); } } class Helper{ private $conn = null; public function __construct(&$dns){ $this->conn = mysql_connect($dns['host'].":".$dns['port'],$dns['user'],$dns['pwd']) or httpError("handler500","数据库出错"); mysql_select_db($dns['db'],$this->conn) or httpError("handler500",$dns['db']."库出现异常"); } public function getConn(){ return $this->conn; } } ?>