不要问我为嘛还在用ThinkPHP 3.2.3 ~~因为稳定就行(不敢升级TP5、变化太大怕有问题)
因为项目中需要做一个后台的长时间的操作任务,因此需要在执行任务之前彻底断开与数据库的连接~~ 也就是能够在MySQL Workbench中的Status页面中看到Connections减少!
百度了一番,看到有人使用了下面的方法 (在Common|Api模式下,位于ThinkPHP\Library\Think\Model.class.php
文件中的 db( $linkNum='',$config='',$force=false )
函数
$Model-> db(0,null) ;
db函数的代码如下所示
/**
* 切换当前的数据库连接
* @access public
* @param integer $linkNum 连接序号
* @param mixed $config 数据库连接信息
* @param boolean $force 强制重新连接
* @return Model
*/
public function db($linkNum='',$config='',$force=false) {
if('' === $linkNum && $this->db) {
return $this->db;
}
if(!isset($this->_db[$linkNum]) || $force ) {
// 创建一个新的实例
if(!empty($config) && is_string($config) && false === strpos($config,'/')) { // 支持读取配置参数
$config = C($config);
}
$this->_db[$linkNum] = Db::getInstance($config);
}elseif(NULL === $config){
$this->_db[$linkNum]->close(); // 关闭数据库连接
unset($this->_db[$linkNum]);
return ;
}
// 切换数据库连接
$this->db = $this->_db[$linkNum];
$this->_after_db();
// 字段检测
if(!empty($this->name) && $this->autoCheckFields) $this->_checkTableInfo();
return $this;
}
这个db函数主要用于切换当前数据库的连接,当第2个参数$config
为 null 的时候,将会调用 close
方法(第21行),这个close方法对应的是ThinkPHP\Library\Think\Db\Driver.class.php
中的close方法,对应的原始代码如下
/**
* 关闭数据库
* @access public
*/
public function close() {
$this->_linkID = null;
}
上述代码中,只是简单的将当前使用的PDO
对象赋值为null
。对于PDO
方式连接数据库而言,只需要将对应的PDO
对象赋值为null
释放即可断开连接。
但是!!!根据官方的文档说明,只要当所有的 PDO
引用全部释放之后才会断开连接。这里将_linkID 直接赋值为null,并没有实现释放所有的PDO引用,经过查看源代码之后发现,在Driver.class.php中还有一个$this->linkID的数组,这个数组会根据连接序号(作为索引)来保存对应的PDO对象,因此这个数组中也引用了PDO对象,此外还有一个PDOStatement对象也需要释放。
修改一下close方法:
/**
* 关闭数据库 ,释放 linkID数组中的PDO引用、_linkID PDO引用以及PDOStatement引用
* @access public
*/
public function close() {
// 删除 数组中的 PDO引用
foreach($this->linkID as $k => &$pdo){
if($pdo === $this->_linkID){
$this->linkID[$k] = null;
break;
}
}
//删除当前 引用的 PDO
$this->_linkID = null;
// 删除 PDOStatement 不然 不会关闭
$this->free();
}
然后再次使用 $Model->db( [序号] ,null);就可以释放对应的数据库连接了。
转载请注明:悠然品鉴 » ThinkPHP3.2 关闭/断开数据库连接