- 浏览: 202963 次
- 性别:
- 来自: 重庆
文章分类
最新评论
自己实现了php的读写分离,并且不用修改程序
优点:实现了读写分离,不依赖服务器硬件配置,并且都是可以配置read服务器,无限扩展
缺点:错误转移不购明确,现只有3次尝试机会,失败了就会选择其他的服务器.当服务器恢复时,需要手动去消除错误日志不人性化
修改于discux x 的mysql类
配置文件
"db"=>array(
'1'=>array(
'dbhost'=> '127.0.0.1',
'dbuser' => 'root',
'dbpw' => 'xxx',
'dbcharset' => 'utf8',
'pconnect' => '0',
'dbname' => 'test',
'tablepre' => 'w_',
),
'2'=>array(
'dbhost'=> '127.0.0.1',
'dbuser' => 'root',
'dbpw' => 'xxx',
'dbcharset' => 'utf8',
'pconnect' => '0',
'dbname' => 'test2',
'tablepre' => 'w_',
),
'3'=>array(
'dbhost'=> '127.0.0.1',
'dbuser' => 'root',
'dbpw' => 'xxx',
'dbcharset' => 'utf8',
'pconnect' => '0',
'dbname' => 'test3',
'tablepre' => 'w_',
),
'writes'=>array('2','3'),
'reads'=>array('2','1'),
'broken'=>array(),
'broken_file'=>str_replace('\\','/',dirname(__FILE__)) ."/____mysql_broken_file.php",
//'broken_file'=>array(),
)
类文件
<?php
/*
[Discuz!] (C)2001-2009 Comsenz Inc.
This is NOT a freeware, use is subject to license terms
$Id: db_mysql.class.php 20294 2009-09-23 06:00:37Z zhaoxiongfei $
*/
if(!defined('IN_APP')) {
exit('Access Denied');
}
class lib_db_mysql extends app_lib
{
var $tablepre;
var $version = '';
var $querynum = 0;
var $curlink;
var $link = array();
var $config = array();
var $sqldebug = array();
var $map = array();
var $reads=array();//读服务器id
var $writes=array();//写服务器id
var $broken=array();//重试3次坏掉的服务器
var $broken_file="";
function init(){
$this->set_config(config_item('db'));
}
function set_config($config) {
$this->config = &$config;
$this->tablepre = $config['1']['tablepre'];
if(!empty($this->config['map'])) {
$this->map = $this->config['map'];
}
/**
* 读写分离
*/
if(!empty($this->config['reads'])) {
$this->reads=$this->config['reads'];
unset($this->config['reads']);
}
if(!empty($this->config['writes'])) {
$this->writes=$this->config['writes'];
unset($this->config['writes']);
}
if(!empty($this->config['broken_file'])) {
$this->broken_file=$this->config['broken_file'];
unset($this->config['broken_file']);
}else{
$this->broken_file=str_replace('\\','/',dirname(__FILE__)) ."/____mysql_broken_file.php";
}
$this->broken=$this->get_broken($this->config['broken']);
unset($this->config['broken']);
//-读写分离
}
function connect($serverid = 1) {
if(empty($this->config) || empty($this->config[$serverid])) {
$this->set_broken($serverid);
$this->halt('config_db_not_found');
}
$this->link[$serverid] = $this->_dbconnect(
$this->config[$serverid]['dbhost'],
$this->config[$serverid]['dbuser'],
$this->config[$serverid]['dbpw'],
$this->config[$serverid]['dbcharset'],
$this->config[$serverid]['dbname'],
$this->config[$serverid]['pconnect'],
$serverid
);
$this->curlink = $this->link[$serverid];
}
function _dbconnect($dbhost, $dbuser, $dbpw, $dbcharset, $dbname, $pconnect,$serverid=0) {
$link = null;
$func = empty($pconnect) ? 'mysql_connect' : 'mysql_pconnect';
if(!$link = @$func($dbhost, $dbuser, $dbpw, 1)) {
$this->set_broken($serverid);
$this->halt('notconnect');
} else {
$this->curlink = $link;
if($this->version() > '4.1') {
$dbcharset = $dbcharset ? $dbcharset : $this->config[1]['dbcharset'];
$serverset = $dbcharset ? 'character_set_connection='.$dbcharset.', character_set_results='.$dbcharset.', character_set_client=binary' : '';
$serverset .= $this->version() > '5.0.1' ? ((empty($serverset) ? '' : ',').'sql_mode=\'\'') : '';
$serverset && mysql_query("SET $serverset", $link);
}
$dbname && @mysql_select_db($dbname, $link);
}
return $link;
}
function table($tablename) {
if(!empty($this->map) && !empty($this->map[$tablename])) {
$id = $this->map[$tablename];
if(!$this->link[$id]) {
$this->connect($id);
}
$this->curlink = $this->link[$id];
} else {
$this->curlink = $this->link[1];
}
return $this->tablepre.$tablename;
}
function select_db($dbname) {
return mysql_select_db($dbname, $this->curlink);
}
function fetch_array($query, $result_type = MYSQL_ASSOC) {
return mysql_fetch_array($query, $result_type);
}
function fetch_first($sql) {
return $this->fetch_array($this->query($sql));
}
function result_first($sql) {
return $this->result($this->query($sql), 0);
}
/**
* 读写分离,并从池中选中随机选中数据库
* 如果没有read连接将使用write代替
*
* @param string $sql
*/
function switch_server($sql,$default=1){
$sql=ltrim($sql);
if(preg_match('/^select/i',$sql)){
$type='reads';
}else{
$type='writes';
}
$servers=array_diff($this->$type,$this->filter_broken($this->broken));
if(!$servers&&$type=='reads'){
$type='writes';
$servers=array_diff($this->$type,$this->filter_broken($this->broken));
}
$t=count($servers);
if($t>0){
//有合理的服务
/**
* 根据ip的hash随机抽服务器运行,
*/
$servers=array_values($servers);
$onlineip = '';
if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
$onlineip = getenv('HTTP_CLIENT_IP');
} elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
$onlineip = getenv('HTTP_X_FORWARDED_FOR');
} elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
$onlineip = getenv('REMOTE_ADDR');
} elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
$onlineip = $_SERVER['REMOTE_ADDR'];
}
!$onlineip&&$onlineip=rand(100);
$i=abs(crc32($onlineip))%$t;
return $servers[$i];
}
return $default;
}
function set_broken($server_id){
$this->broken[$server_id]++;
if($this->broken_file){
$str=var_export($this->broken,true);
$c="<?php
\$broken=$str;
?>";
return file_put_contents($this->broken_file,$c);
}
}
function filter_broken($broken){
$error_try=3;
foreach($broken as $id=>$num){
if($num<$error_try){
unset($broken[$id]);
}
}
return array_keys($broken);
}
function get_broken($realbroken){
$broken=array();
$error_try=3;
if($this->broken_file&&is_file($this->broken_file)){
@include($this->broken_file);
}
settype($realbroken,'array');
foreach($realbroken as $id){
$broken[$id]=$error_try;
}
return $broken;
}
/**
* 读写分离
*
* @param mixed $sql
* @param mixed $type
*/
function query($sql, $type = '') {
if(defined('DISCUZ_DEBUG') && DISCUZ_DEBUG) {
$starttime = dmicrotime();
}
//读写分离
$server_id=$this->switch_server($sql,1);
if($this->link[$server_id]){
$this->curlink=$this->link[$server_id];
}else{
$this->connect($server_id);
}
//-读写分离
$func = $type == 'UNBUFFERED' && @function_exists('mysql_unbuffered_query') ?
'mysql_unbuffered_query' : 'mysql_query';
if(!($query = $func($sql, $this->curlink))) {
if(in_array($this->errno(), array(2006, 2013)) && substr($type, 0, 5) != 'RETRY') {
$this->connect($server_id);
return $this->query($sql, 'RETRY'.$type);
}
if($type != 'SILENT' && substr($type, 5) != 'SILENT') {
$this->halt('query_error', $sql);
}
}
if(defined('DISCUZ_DEBUG') && DISCUZ_DEBUG) {
$this->sqldebug[] = array($sql, number_format((dmicrotime() - $starttime), 6), debug_backtrace());
}
$this->querynum++;
return $query;
}
function affected_rows() {
return mysql_affected_rows($this->curlink);
}
function error() {
return (($this->curlink) ? mysql_error($this->curlink) : mysql_error());
}
function errno() {
return intval(($this->curlink) ? mysql_errno($this->curlink) : mysql_errno());
}
function result($query, $row = 0) {
$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->curlink)) >= 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() {
if(empty($this->version)) {
$this->version = mysql_get_server_info($this->curlink);
}
return $this->version;
}
function close() {
return mysql_close($this->curlink);
}
function halt($message = '', $sql = '') {
global $_G;
$dberror = $this->error();
$dberrno = $this->errno();
$phperror = '<table style="font-size:11px" cellpadding="0"><tr><td width="270">File</td><td width="80">Line</td><td>Function</td></tr>';
foreach (debug_backtrace() as $error) {
$error['file'] = str_replace(DISCUZ_ROOT, '', $error['file']);
$error['class'] = isset($error['class']) ? $error['class'] : '';
$error['type'] = isset($error['type']) ? $error['type'] : '';
$error['function'] = isset($error['function']) ? $error['function'] : '';
$phperror .= "<tr><td>$error[file]</td><td>$error[line]</td><td>$error[class]$error[type]$error[function]()</td></tr>";
}
$phperror .= '</table>';
$helplink = "http://faq.comsenz.com/?type=mysql&dberrno=".rawurlencode($dberrno)."&dberror=".rawurlencode($dberror);
@header('Content-Type: text/html; charset='.$_G['config']['output']['charset']);
echo '<div style="position:absolute;font-size:11px;font-family:verdana,arial;background:#EBEBEB;padding:0.5em;line-height:1.5em">';
echo "<b>PHP Backtrace</b><br />$sql error<br /> $dberror</div>";
exit();
}
function delete($table, $condition, $limit = 0, $unbuffered = true) {
if(empty($condition)) {
$where = '1';
} elseif(is_array($condition)) {
$where = $this->implode_field_value($condition, ' AND ');
} else {
$where = $condition;
}
$sql = "DELETE FROM ".$this->table($table)." WHERE $where ".($limit ? "LIMIT $limit" : '');
return $this->query($sql, ($unbuffered ? 'UNBUFFERED' : ''));
}
function insert($table, $data, $return_insert_id = false, $replace = false, $silent = false) {
$sql = $this->implode_field_value($data);
$cmd = $replace ? 'REPLACE INTO' : 'INSERT INTO';
$table = $this->table($table);
$silent = $silent ? 'SILENT' : '';
$return = $this->query("$cmd $table SET $sql", $silent);
return $return_insert_id ? $this->insert_id() : $return;
}
function update($table, $data, $condition, $unbuffered = false, $low_priority = false) {
$sql = $this->implode_field_value($data);
$cmd = "UPDATE ".($low_priority ? 'LOW_PRIORITY' : '');
$table = $this->table($table);
$where = '';
if(empty($condition)) {
$where = '1';
} elseif(is_array($condition)) {
$where = $this->implode_field_value($condition, ' AND ');
} else {
$where = $condition;
}
$res = $this->query("$cmd $table SET $sql WHERE $where", $unbuffered ? 'UNBUFFERED' : '');
return $res;
}
function implode_field_value($array, $glue = ',') {
$sql = $comma = '';
foreach ($array as $k => $v) {
$sql .= $comma."`$k`='$v'";
$comma = $glue;
}
return $sql;
}
}
发表评论
-
验证码识别与破解
2012-12-29 15:50 1171连接如下: 1.php实现验证码的破解识别 http:// ... -
分页,MySQL的SQL_CALC_FOUND_ROWS
2012-12-17 16:44 1346FOUND_ROWS() 函数 ,可以在调用包含LIMIT的 ... -
使用mysql的last_insert_id() 产生自增的id
2012-12-17 15:48 1084刚才查了下last_insert_id()相关资料,找到几篇不 ... -
innodb的记录锁、gap锁、next-key锁
2012-12-17 13:45 1388相关文章见: http://dev.mysql ... -
MySQL Innodb表死锁情况分析与归纳(转载)
2012-12-14 16:22 1940案例描述 在定时脚本运行过程中,发现当 ... -
MySQL连接超时
2012-12-13 20:41 1113在负载较重的MySQL服务器上,有时你偶尔会看到一些 ... -
mysql优化索引 —— Using filesort
2012-12-11 12:13 819用Explain分析SQL语句的时候,经常发现有的语句在 ... -
IN条件结果顺序问题
2012-11-23 14:42 663项目中需要记录用户的浏览历史,我的意见是前端直接存cook ... -
mysql那点事(行锁+not null + varchar)
2012-10-12 15:08 1651一。not null vs DEAFUL value ... -
究竟什么是TSRMLS_CC
2012-09-29 12:18 674原文地址:http://blog.libssh2.org ... -
debug_zval_dump()中参数是引用的refcount为1
2012-09-26 23:35 2162在函数传递参数时有引用计数增加操作,举个例子: ... -
深入理解PHP之引用一
2012-09-26 23:35 728PHP是弱语言,其变量 ... -
深入PHP内核(1) 引用
2012-09-29 09:54 618最近,和一个网友交流的时候,给我提了一个非常奇怪 ... -
PHP 引用是个坏习惯
2012-09-29 09:54 573在写PHP 程序的时候,很多人在传递参数的时候,喜欢用一 ... -
深入探讨PHP中的内存管理问题
2012-09-29 09:54 719摘要 内存管理对于长期运行的程序,例如服务器守护程序,是相 ... -
关于mysql auto_increment所带来的锁表操作
2012-09-01 14:00 1606以前内容主要是对官方文档中的意译,并加入了一些自己的理解 ... -
mysql 与unicode
2012-08-29 15:36 1681UTF8字符集(转换Unicode表示)是存储Unico ... -
深入Mysql字符集设置
2012-08-29 14:46 55805 Jan 08 深入Mysql字符集设置 ... -
关于set names
2012-08-29 14:37 809<?php$conn=mysql_connect( ... -
MYSQL索引优化和in or替换为union all
2012-08-22 17:16 4042一个文章库,里面有两个表:category和article。c ...
相关推荐
本文实例讲述了PHP实现的mysql读写分离操作。分享给大家供大家参考,具体如下: 首先mysql主从需配置好,基本原理就是判断sql语句是否是select,是的话走master库,否则从slave查 <?php /** * mysql读写分离 */ ...
相对于其他方法实现MySQL的读写分离来说,采用Thinkphp框架实现MySQL的读写分离简单易用,其配置文件示例代码如下: 'DB_TYPE'=> 'mysql', 'DB_DEPLOY_TYPE' => 1, //开打支持多服务器 'DB_RW_SEPARATE'=>true,//...
主要介绍了php实现带读写分离功能的MySQL类,具有针对mysql数据库的基本增删改查及读写分离操作的功能,涉及针对读库与写库的判断及操作技巧,需要的朋友可以参考下
基于此,我们再实现简单的PHP+Mysql读写分离,从而提高数据库的负载能力。 2、代码实战 <?php class Db { private $res; function __construct($sql) { $querystr = strtolower(trim(substr($sql,0,6))); ...
本代码是从uchome的代码修改的,是因为要解决uchome的效率而...PHP实现的Mysql读写分离主要特性:1.简单的读写分离 2.一个主数据库,可以添加更多的只读数据库 3.读写分离但不用担心某些特性不支持 4.缺点:同时连接
thinkphp核心类Thinkphp/library/Model.class.php 中,query 方法,调用Thinkphp/library/Think/Db/Driver/Mysql.class.php /** * SQL查询 * @access public * @param string $sql SQL * @
C E CCIC宋青见在2017PHP全球开发者大会上做了主题为《云原生的 MySQL 托管服务架构及读写分离的优化(PHP)》的演讲,就云原生的Azure RDS for MySQL托管服务架构,读写分离的优化,微服务架构Service Fabric的介绍做...
本文实例讲述了php实现的mysqldb读写分离操作类。分享给大家供大家参考,具体如下: /** * php MysqlDB 读写分离类 * ----------------------------------------------------- * $Source: ...
mysql-proxy实现读写分离 MySQL Proxy是一个处于你的client端和MySQL server端之间的简单程序,它可以监测、分析或改变它们的通信。它使用灵活,没有限制,常见的用途包括:负载平衡,故障、查询分析,查询过滤和...
本文实例分析了Yii实现MySQL多数据库和读写分离的方法。分享给大家供大家参考。具体分析如下: Yii Framework是一个基于组件、用于开发大型 Web 应用的高性能 PHP 框架。Yii提供了今日Web 2.0应用开发所需要的几乎...
技术文档分享。
完整版 MySQL8.0从入门到精通 MySQL数据库教程 第20章 读写分离的利器-MySQL Proxy(共8页).ppt 完整版 MySQL8.0从入门到精通 MySQL数据库教程 第21章 精通MySQL存储引擎(共31页).ppt 完整版 MySQL8.0从入门到...
完整版 MySQL8.0从入门到精通 MySQL数据库教程 第20章 读写分离的利器-MySQL Proxy(共8页).ppt 完整版 MySQL8.0从入门到精通 MySQL数据库教程 第21章 精通MySQL存储引擎(共31页).ppt 完整版 MySQL8.0从入门到...
使其支持读写分离、支持Smarty模板、支持页面和动作代码分离、支持nosql类的mongdb,主要特点有: ◆数据库连接做自动主从读写分离配置,适合单机和分布式站点部署; ◆支持Smarty模板机制,可灵活配置第三方...
第十一部 MySQL读写分离开发实现及软件实现-物理备份-高可用(已经包含有5节视频+文档资料) 01-amoeba读写分离实现技术分享.avi 02-mysql-proxy读写分离实现技术分享.avi 03-PHP程序实现读写分离技术分享.avi 04-...
第20讲 读写分离的利器——MySQL Proxy 第21讲 精通MySQL存储引擎 第22讲 PHP操作mysql数据库 第23讲 PDO数据库抽象类库 第24讲 开发网上商城 第25讲 论坛管理系统数据库设计 第26讲 新闻发布系统数据库设计 课本...