读写分离MYSQL类
2014年4月27日 12:34:08
概述:
1. 根据sql语句判断是连接读库还是写库
2. 链式调用$this->where()->get()
3. 不同的主机对应不同的实例, 不再多次new
<?php
class DBRWmysql
{
private static $Instance = null; private $links = array();//链接数组
private $link = null; //当前连接
public $dbType = 'read'; public $_host=''; //数据库所在主机名
public $_database = '';//当前数据库名
public $_tablename = '';//当前表的表名
public $_dt ='';//database.tablename
public $isRelease = 0; //查询完成后是否释放 public $fields = '*';
public $arrWhere = [];
public $order = '';
public $arrOrder = [];
public $limit = '';
public $sql = ''; public $rs;//结果集 private function __construct($database='', $tablename='', $isRelease=0)
{
$this->_database = $database;//database name
$this->_tablename = $tablename;//table name
$this->_dt = "`{$this->_database}`.`{$this->_tablename}`";
$this->isRelease = $isRelease;
} public static function getInstance($database='', $tablename='', $isRelease=0)
{
if (self::$Instance == null) {
self::$Instance = new DBRWmysql($database, $tablename, $isRelease);
} self::$Instance->_database = $database;
self::$Instance->_tablename = $tablename;
self::$Instance->_dt = "`{$database}`.`{$tablename}`";
self::$Instance->isRelease = $isRelease; return self::$Instance;
} //如果主机没变,并且已经存在MYSQL连接,就不再创建新的连接
//如果主机改变,就再生成一个实例创建一个连接
//type == 'write'或'read'
public function getLink($type)
{
$this->dbType = $$type; //随机选取一个数据库连接(区分读写)
$dbConfig = DBConfig::$$type;
$randKey = array_rand($dbConfig);
$config = $dbConfig[$randKey]; //链接数据库
$host = $config['host'];
$username = $config['username'];
$password = $config['password']; if (empty($this->links[$host])) {
$this->_host = $host;
$this->links[$host] = new mysqli($host, $username, $password);
if($this->links[$host]->connect_error) {
$this->error($this->links[$host]->connect_error);
}
} //初始化链接
$this->link = $this->links[$host];
$this->link->query("set names utf8mb4;"); //支持emoji表情
$this->link->query("use {$this->_database};");
} public function getCurrentLinks()
{
return $this->links;
} //析构函数
public function __destruct()
{
foreach ($this->links as $v) {
$v->close();
}
} //查询封装
public function query($sql)
{
$this->sql = $sql;
if (strpos($sql, 'select') !== false) {
$this->getLink('read');//读库
} else {
$this->getLink('write');//写库
} $this->rs = $this->link->query($sql);
($this->rs === false) && $this->error('sql error: '.$sql.PHP_EOL.$this->link->error); //查询完成后释放链接, 并删除链接对象
if ($this->isRelease) {
$this->link->close();
unset($this->links[$this->_host]);
}
return $this->rs;
} //增
public function insert($arrData)
{
foreach ($arrData as $key=>$value) {
$fields[] = $key;
$values[] = "'".$value."'";
// $fields[] = '`'.$key.'`';
// $values[] = "'".$value."'";
}
$strFields = implode(',', $fields);
$strValues = implode(',', $values);
$sql = "insert into {$this->_dt} ($strFields) values ($strValues)";
$this->query($sql);
$insert_id = $this->link->insert_id; return $insert_id;
} //增
public function replace($arrData)
{
foreach ($arrData as $key=>$value) {
$fields[] = $key;
$values[] = "'{$value}'";
}
$strFields = implode(',', $fields);
$strValues = implode(',', $values);
$sql = "replace into {$this->_dt} ($strFields) values ($strValues)"; $this->query($sql); return $this->link->insert_id;
} //增
//每次插入多条记录
//每条记录的字段相同,但是值不一样
public function insertm($arrFields, $arrData)
{
foreach ($arrFields as $v) {
// $fields[] = "`{$v}`";
$fields[] = $v;
} foreach ($arrData as $v) {
$data[] = '('.implode(',', $v).')';
} $strFields = implode(',', $fields);
$strData = implode(',', $data); $sql = "insert into {$this->_dt} ($strFields) values {$strData}"; $this->query($sql); return $this->link->insert_id;
} //删
public function delete()
{
$where = $this->getWhere();
$limit = $this->getLimit(); $sql = " delete from {$this->_dt} {$where} {$limit}";
$this->query($sql);
return $this->link->affected_rows;
} //改
public function update($data)
{
$where = $this->getWhere(); $arrSql = array();
foreach ($data as $key=>$value) {
$arrSql[] = "{$key}='{$value}'";
}
$strSql = implode(',', $arrSql); $sql = "update {$this->_dt} set {$strSql} {$where} {$this->limit}"; $this->query($sql); return $this->link->affected_rows; } //获取总数
public function getCount()
{
$where = $this->getWhere(); $sql = " select count(1) as n from {$this->_dt} {$where} ";
$resault = $this->query($sql); ($resault===false) && $this->error('getCount error: '.$sql); $arrRs = $this->rsToArray($resault); $num = array_shift($arrRs);
return $num['n'];
} //将结果集转换成数组返回
//如果field不为空,则返回的数组以$field为键重新索引
public function rsToArray($field = '')
{
$arrRs = $this->rs->fetch_all(MYSQLI_ASSOC); //该函数只能用于php的mysqlnd驱动
$this->rs->free();//释放结果集 if ($field) {
$arrResult = [];
foreach ($arrRs as $v) {
$arrResult[$v[$field]] = $v;
}
return $arrResult;
} return $arrRs;
} //给字段名加上反引号
public function qw($strFields)
{
$strFields = preg_replace('#\s+#', ' ', $strFields);
$arrNewFields = explode(' ', $strFields );
$arrNewFields = array_filter($arrNewFields);
foreach ($arrNewFields as $k => $v) {
$arrNewFields[$k]= '`'.$v.'`';
}
return implode(',', $arrNewFields);
} //处理入库数据,将字符串格式的数据转换为...格式(未实现)
public function getInsertData($strData)
{
// $bmap = "jingdu,$jingdu weidu,$weidu content,$content";
} //select in
//arrData 整数数组,最好是整数
public function select_in($key, $arrData, $fields='')
{
$fields = $fields ? $fields : '*';
sort($arrData);
$len = count($arrData);
$cur = 0;
$pre = $arrData[0]; $new = array('0' => array($arrData[0]));
for ($i = 1; $i < $len; $i++) {
if (($arrData[$i] - $pre) == 1 ) {
$new[$cur][] = $arrData[$i];
} else {
$cur = $i;
$new[$cur][] = $arrData[$i];
}
$pre = $arrData[$i];
} $arrSql = array();
foreach ($new as $v) {
$len = count($v) - 1;
if ($len) {
$s = $v[0];
$e = end($v);
$sql = "(select $fields from {$this->_dt} where $key between $s and $e)";
} else {
$s = $v[0];
$sql = "(select $fields from {$this->_dt} where $key = $s)";
} $arrSql[] = $sql;
} $strUnion = implode(' UNION ALL ', $arrSql);
$res = $this->query($strUnion);
return $this->rstoarray($res);
} //where in
public function setWhereIn($key, $arrData)
{
if (empty($arrData)) {
$str = "(`{$key}` in ('0'))";
$this->addWhere($str);
return $str;
} foreach ($arrData as &$v) {
$v = "'{$v}'";
}
$str = implode(',', $arrData);
$str = "(`{$key}` in ( {$str} ))"; $this->addWhere($str); return $this;
} //where in
public function setWhere($arrData)
{
if (empty($arrData)) {
return '';
} foreach ($arrData as $k => $v) {
$str = "(`{$k}` = '{$v}')";
$this->addWhere($str);
} return $this;
} //between and
public function setWhereBetween($key, $min, $max)
{
$str = "(`{$key}` between '{$min}' and '{$max}')";
$this->addWhere($str);
return $this;
} //where a>b
public function setWhereBT($key, $value)
{
$str = "(`{$key}` > '{$value}')";
$this->addWhere($str);
return $this;
} //where a<b
public function setWhereLT($key, $value)
{
$str = "(`{$key}` < '{$value}')";
$this->addWhere($str);
return $this;
} //组装where条件
public function addWhere($where)
{
$this->arrWhere[] = $where;
} //获取最终查询用的where条件
public function getWhere()
{
if (empty($this->arrWhere)) {
return 'where 1';
} else {
return 'where '.implode(' and ', $this->arrWhere);
}
} //以逗号隔开
public function setFields($fields)
{
$this->fields = $fields;
return $this;
} // order by a desc
public function setOrder($order)
{
$this->arrOrder[] = $order;
return $this;
} //获取order语句
public function getOrder()
{
if (empty($this->arrOrder)) {
return '';
} else {
$str = implode(',', $this->arrOrder);
$this->order = "order by {$str}";
}
return $this->order;
} //e.g. '0, 10'
//用limit的时候可以加where条件优化:select ... where id > 1234 limit 0, 10
public function setLimit($limit)
{
$this->limit = 'limit '.$limit;
return $this;
} //直接查询sql语句, 返回数组格式
public function arrQuery($sql, $field='')
{
$this->query($sql);
$this->clearQuery();
($this->rs===false) && $this->error('select error: '.$sql);
return $this->rsToArray($field);
} //如果 $field 不为空, 则返回的结果以该字段的值为索引
//暂不支持join
public function get($field='')
{
$where = $this->getWhere();
$order = $this->getOrder(); $sql = " select {$this->fields} from {$this->_dt} {$where} {$order} {$this->limit} ";
return $this->arrQuery($sql, $field);
} //获取一条记录
public function getOne()
{
$this->setLimit(1);
$rs = $this->get(); return !empty($rs) ? $rs[0] : [];
} //获取一条记录的某一个字段的值
public function getOneField($field)
{
$this->setFields($field);
$rs = $this->getOne(); return !empty($rs[$field]) ? $rs[$field] : '';
} //获取数据集中所有某个字段的值
public function getFields($field)
{
$this->setFields($field);
$rs = $this->get();
$result = [];
foreach ($rs as $v) {
$result[] = $v[$field];
}
unset($rs); return $result;
} //清除查询条件
//防止干扰下次查询
public function clearQuery()
{
$this->fields = '*';
$this->arrWhere = [];
$this->order = '';
$this->arrOrder = [];
$this->limit = '';
} //断开数据库连接
public function close()
{
$this->link->close();
} //事务
//自动提交开关
public function autocommit($bool)
{
$this->link->autocommit($bool);
} //事务完成提交
public function commit()
{
$this->link->commit();
} //回滚
public function rollback()
{
$this->link->rollback();
} //输出错误sql语句
public function error($sql)
{
//if (IS_TEST) {}
exit($sql);
}
}
最后编辑: 2016年4月16日 19:45:14 星期六
读写分离MYSQL类的更多相关文章
- mysql读写分离(PHP类)
mysql读写分离(PHP类) 博客分类: php mysql 自己实现了php的读写分离,并且不用修改程序 优点:实现了读写分离,不依赖服务器硬件配置,并且都是可以配置read服务器,无限扩展 ...
- LVS+MYCAT+读写分离+MYSQL主备同步部署手册
LVS+MYCAT+读写分离+MYSQL主备同步部署手册 1 配置MYSQL主备同步…. 2 1.1 测试环境… 2 1.2 配置主数据库… 2 1.2.1 ...
- 【转载】LVS+MYCAT+读写分离+MYSQL主备同步部署手册(邢锋)
LVS+MYCAT+读写分离+MYSQL主备同步部署手册 1 配置MYSQL主备同步…. 2 1.1 测试环境… 2 1.2 配置主数据库… 2 1.2.1 ...
- LVS+MYCAT读写分离+MYSQL同步部署手册(第三版)
1 配置MYSQL主备同步 1.1 测试环境 mysql版本:5.6.24: 操作系统内核版本:Linux-3.13-0-32 主数据库IP:192.168.10.3: 主数据库名:d ...
- 数据切分——Atlas读写分离Mysql集群的搭建
关于数据切分的原理可以参见博客: http://blog.csdn.net/jhq0113/article/details/44226789 关于Atlas的介绍可以参见博客: http://blog ...
- 三十五.MySQL读写分离 MySQL多实例 、MySQL性能调优
1.实现MySQL读写分离 搭建一主一从结构 配置maxscale代理服务器 测试分离配置 1.1 搭建一主一从结构 192.168.4.51 主 192.168.4.52 从 测试OK 1. ...
- MyCat读写分离+MySql主从(一主一从)
数据库一直在项目担当着一位核心的角色,是所有项目结构中的底层,说白了,我们程序员进行项目开发都是在和数据打交道,而数据都是保存在数据库中,如mysql.oracle.postgresql等等,如果一个 ...
- MySQL+Amoeba实现数据库主从复制和读写分离
MySQL读写分离是在主从复制的基础上进一步通过在master上执行写操作,在slave上执行读操作来实现的.通过主从复制,master上的数据改动能够同步到slave上,从而保持了数据的一致性.实现 ...
- ProxySQL+Mysql实现数据库读写分离实战
ProxySQL介绍 ProxySQL是一个高性能的MySQL中间件,拥有强大的规则引擎.具有以下特性:http://www.proxysql.com/ 1.连接池,而且是multiplexing 2 ...
随机推荐
- Beta 冲刺 三
团队成员 051601135 岳冠宇 031602629 刘意晗 031602248 郑智文 031602330 苏芳锃 031602234 王淇 照片 项目进展 岳冠宇 ## 项目进展 昨天的困难 ...
- Selenium WebDriver VS Selenium RC
WebDriver到底是什么? WebDriver是一个Web的自动化测试框架,它支持你执行你的测试用例在不同的浏览器上面,并不像Selenium一样只支持Firefox. WebDriv ...
- Linux命令(二十一) 改变文件所有权 chown 和 chgrp
目录 1.命令简介 2.常用参数介绍 3.实例 4.直达底部 命令简介 一个文件属于特定的所有者,如果更改文件的属主或属组可以使用 chown 和 chgrp 命令. chown 命令可以将文件变更为 ...
- MongoDB入门 和nodejs操作
简介 MongoDB 开源,高性能的NoSQL数据库:支持索引.集群.复制和故障转移.各种语言的驱动程序:高伸缩性: NoSQL毕竟还处于发展阶段,也有说它的各种问题的:http://coolshel ...
- SQL 中LTrim、RTrim与Trim的用法
LTrim.RTrim与 Trim 函数 返回 Variant (String),其中包含指定字符串的拷贝,没有前导空白 (LTrim).尾随空白 (RTrim) 或前导和尾随空白 (Trim).语法 ...
- 一本通1646GT 考试
1646:GT 考试 时间限制: 1000 ms 内存限制: 524288 KB [题目描述] 阿申准备报名参加 GT 考试,准考证号为 n 位数 X1X2⋯Xn(0≤Xi≤9),他不 ...
- c语言基础——基本数据类型
1.基本数据类型是什么?包括有哪些代表?除了基本数据类型还有什么其他类型形式? (1)基本数据类型--用于描述基本的数据 (数.日期等) (2)有整型.实型.字符型.枚举类型等等 ========== ...
- 在Mac上配置全局的Git忽略文件
现在同时搞着好几个项目,在Xcode.IDEA.Eclipse之间频繁的切换,每个项目的忽略文件列表都不一样,每个项目都有一个.gitignore,甚是麻烦,今天网上拔出来一个设置全局忽略的办法,记录 ...
- PyCharm远程开发配置及一些问题的解决方案
PyCharm远程开发配置 具体请参考:https://www.jianshu.com/p/79df9ac88e96 Tips:必须要安装PyCharm专业版 实践过程中遇到的问题 背景 因项目需要, ...
- 走楼梯(walk) 解题报告
走楼梯(walk) 题意 给一个长为\(n(1\le n\le 10^5)\)序列\(\{a\}\),每次从中间挖掉\([l,r]\),然后询问最长上升子序列,强制在线. 有一档分是30000和离线, ...