[PHP] PHP PDO与mysql的连接单例防止超时情况处理
这个数据库类主要处理了单例模式下创建数据库对象时,如果有两次较长时间的间隔去执行sql操作,再次处理会出现连接失败的问题,利用一个cache数组存放pdo对象与时间戳,把两次执行之间的时间进行了比较,如果间隔超过了10秒就再次new PDO创建连接,没有超过的情况下会继续使用原来的连接,并且因为每次使用后会使连接续期,cache数组里的时间戳也进行了续期.
每次执行操作都会从cache数组中获取下连接,多次执行不超过10秒的情况下,只会有一个连接
代码中实现读写分离,判断sql语句前面6个字符是select的就查询从库,其余操作查询主库.主库和从库就是分别在配置数组中0和1创建不同的PDO对象连接
代码如下:
<?php
class SinaPdoAdapter{
const MASTER = 0;
const SLAVE = 1;
const DEFAULT_CACHE_EXPIRETIME = 10;
private static $options = array(
PDO::ATTR_AUTOCOMMIT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
//PDO::ATTR_PERSISTENT => true,
);
private $dsn = null;
private $username = null;
private $password = null;
private $timeout = null;
private $charset = null;
private $conns = array();
private $conn = null;
private $stmt = null;
private static $obj=null;
private function __construct($dsn, $username, $password, $timeout = null, $charset = null){
$this->dsn = $dsn;
if (!is_array($username)) {
$this->username = array($username);
} else {
$this->username = $username;
}
if (!is_array($password)) {
$this->password = array($password);
} else {
$this->password = $password;
}
$this->timeout = intval($timeout);
$this->charset = $charset;
}
private function getConnection($id = self::MASTER){
if (!isset($this->dsn[$id])) {
$id = self::MASTER;
}
$conn = $this->getCachedConn($id);
if ($conn) {
return $conn;
}
$opts = self::$options;
if ($this->timeout > 0) {
$opts[PDO::ATTR_TIMEOUT] = $this->timeout;
}
$username = isset($this->username[$id]) ? $this->username[$id] : $this->username[self::MASTER];
$password = isset($this->password[$id]) ? $this->password[$id] : $this->password[self::MASTER];
$conn = new PDO($this->dsn[$id], $username, $password, $opts);
$this->cacheConn($id, $conn);
if ($this->charset) {
$conn->exec('set names ' . $this->charset);
}
return $conn;
} public function execute($sql, $params = array()){
$cmd = substr($sql, 0, 6);
if (strcasecmp($cmd, 'select') === 0) {
$conn = $this->getConnection(self::SLAVE);
} else {
$conn = $this->getConnection(self::MASTER);
}
$stmt = $conn->prepare($sql);
$stmt->execute($params);
$this->stmt = $stmt;
$this->conn = $conn;
} public function fetch(){
return $this->stmt->fetch();
} public function fetchAll(){
return $this->stmt->fetchAll();
}
public function lastInsertId(){
return $this->conn->lastInsertId();
}
public function rowCount(){
return $this->stmt->rowCount();
} public static function getInstance($conf){
if(self::$obj == null){
self::$obj = new self($conf->dsn,$conf->username,$conf->password,$conf->timeout,$conf->charset);
}
return self::$obj;
} private function getCachedConn($id){
if (!isset($this->conns[$id])) {
return null;
}
list($conn, $timeout) = $this->conns[$id];
if (time() < $timeout) {
$this->cacheConn($id, $conn);
return $conn;
} else {
return null;
}
}
private function cacheConn($id, $conn){
$timeout = time();
if ($this->timeout) {
$timeout += $this->timeout;
} else {
$timeout += self::DEFAULT_CACHE_EXPIRETIME;
}
$this->conns[$id] = array($conn, $timeout);
}
} $config=new stdClass();
$config->dsn=array(
"mysql:host=127.0.0.1;port=3306;dbname=surframe",//主库
"mysql:host=127.0.0.2;port=3306;dbname=surframe"//从库
);
$config->username=array(
'root', 'root',
);
$config->password=array(
'taoshihan1', 'taoshihan1',
);
$config->timeout=10;
$config->charset="utf8"; $db=SinaPdoAdapter::getInstance($config);
$db->execute("select * from admin_users");//使用的从库
$rows=$db->fetchAll();
var_dump($db); $db=SinaPdoAdapter::getInstance($config);
$db->execute("select * from admin_users");//使用的从库
$rows=$db->fetchAll();
var_dump($db);
[PHP] PHP PDO与mysql的连接单例防止超时情况处理的更多相关文章
- java设计模式——单例(Singleton)模式
在某些场景,你需要找到一个承担职责的对象,并且这个对象是他所属类的唯一实例.此时可以使用单例模式. 单例模式的意图是为了确保一个类有且仅有一个实例,并为他提供一个全局的访问点.创建一个担当独一无二角色 ...
- 设置模式之单例模式(附上一个Objective-C编写的播放音乐的单例类)
在查阅Cocoa Touch开发文档时,会发现框架中随处可见的大量单例类,比如说,UIApplication.NSFileManager 等. UIApplication 框架中极为常用的一个单例类, ...
- java 中的懒汉单例和饿汉单例模式
//-------------------------------------------------------------饿汉模式--开始----------------------------- ...
- spring中的单例和多例
单例 对象在整个系统中只有一份,所有的请求都用一个对象来处理,如service和dao层的对象一般是单例的. 为什么使用单例:因为没有必要每个请求都新建一个对象的时候,浪费CPU和内存. 多例 对象在 ...
- Java并发笔记——单例与双重检测
单例模式可以使得一个类只有一个对象实例,能够减少频繁创建对象的时间和空间开销.单线程模式下一个典型的单例模式代码如下: ① class Singleton{ private static Single ...
- php中使用mysqli和pdo扩展,测试连接mysql数据库的效率。
<?php /** * 测试pdo和mysqli的连接效率,各连接100次mysql数据库 */ header("Content-type:text/html;charset=utf8 ...
- [PHP] PDO对象与mysql的连接超时
在php中每一个new的PDO对象,都会去连接mysql,都会创建一条tcp连接.当pdo对象赋予的变量是一个的时候,那么他只会保持一个tcp连接,没有被引用的对象连接会直接断掉.如果不对这个对象进行 ...
- MySQL数据库单例连接简单实现(MySQL扩展)
<?php /** * MySQL数据库单例实现 * * @author shizq at 2015-04-22 * */ final class MySQLFactory { private ...
- PDO之MySql持久化自动重连导致内存溢出
前言 最近项目需要一个常驻内存的脚本来执行队列程序,脚本完成后发现Mysql自动重连部分存在内存溢出,导致运行一段时间后,会超出PHP内存限制退出 排查 发现脚本存在内存溢出后排查了一遍代码,基本确认 ...
随机推荐
- 简单快速上手Jackson使用
1简介 Jackson具有比较高的序列化和反序列化效率,据测试,无论是哪种形式的转换,Jackson > Gson > Json-lib,而且Jackson的处理能力甚至高出Json-li ...
- JNDI学习总结(一)——JNDI数据源的配置
原文地址:http://www.cnblogs.com/xdp-gacl/p/3951952.html 一.数据源的由来 在Java开发中,使用JDBC操作数据库的四个步骤如下: ①加载数据库驱动 ...
- Nginx一般配置
文件为 nginx.conf ,一般配置内容如下: user root;worker_processes auto;#pid /var/run/nginx.pid;#error_log /dev/st ...
- 微信支付和微信支付通知基于sdk的说明(2)
前期准备工作 微信商户账户/密码(获取appid等信息) 微信公众号账户/密码(获取cert证书等信息,不做线上退款不需要证书) 下载php支付demo 从商户平台进入的话是以下界面或者直接搜索公众号 ...
- manjaro安装后的配置
1.添加中科大源 参考https://blog.csdn.net/liyunfu233/article/details/87381017 sudo nano /etc/pacman.conf 在文末添 ...
- python接口自动化根据请求接口类型进行封装
根据不同的请求类型(GET/POST)进行接口请求封装 import requests import json class RunMain: def __init__(self, url, metho ...
- private构造器和单例模式
// hiding/Lunch.java // Demonstrates class access specifiers. Make a class // effectively private wi ...
- linux 库文件配置
linux 库文件配置 /etc/ld.so.conf 或 /etc/ld.so.conf.d/*.conf
- vivado2017.1和modelsim10.5联合仿真
vivado2017.1和modelsim版本 vivado可在xilinx官网查询匹配的modelsim最低版本,下载modelsim前记得选用合适的版本号,如图 查询地址:https://www. ...
- Codechef November Challenge 2019 Division 1
Preface 这场CC好难的说,后面的都不会做QAQ 还因为不会三进制位运算卷积被曲明姐姐欺负了,我真是太菜了QAQ PS:最后还是狗上了六星的说,期待两(三)场之内可以上七星 Physical E ...