在之前咱们手写 mysql 的连贯操作时,个别都会应用 mysql_close() 来进行敞开数据库连贯的操作。不过在现代化的开发中,个别应用框架都会让咱们漠视了底层的这些封装,而且大部分框架都曾经默认是应用 PDO 来进行数据库的操作,那么,大家晓得 PDO 是如何敞开数据的连贯的吗?
官网阐明
要想敞开连贯,须要销毁对象以确保所有残余到它的援用都被删除,能够赋一个 NULL 值给对象变量。如果不明确地这么做,PHP 在脚本完结时会主动敞开连贯。
$pdo = new PDO('mysql:host=127.0.0.1;port=3306;dbname=blog_test', 'root', '');
$pdo = null;
官网文档中说得很明确,那就是给 PDO 对象赋值为 NULL 即可。然而事件真的有那么简略吗?
理论测试
咱们来这样进行一下测试,失常状况下,咱们关上数据库连贯后都不会间接就敞开,而是要进行一些操作。
$pdo = new PDO('mysql:host=127.0.0.1;port=3306;dbname=blog_test', 'root', '');
$stmt = $pdo->prepare('SELECT * FROM zyblog_test_user');
$stmt->execute();
$pdo = null;
sleep(60);
运行上述代码后,咱们在数据库应用 show full processlist; 查看连贯过程,会发现以后的连贯并没有马上敞开,而是等到 60 秒之后,也就是页面执行实现之后才会敞开。仿佛 $pdo = null; 这句并没有执行胜利。
其实,在官网文档中曾经阐明了这个状况,只是大家可能不太会留神。【须要销毁对象以确保所有残余到它的援用都被删除】,在下面的代码中,\$stmt 预编译 SQL 语句的性能调用的是 $pdo 对象中的办法,它们之间产生了援用依赖的关系,这样的状况下,间接给 $pdo = null; 是没有成果的,咱们须要将 $stmt 也赋值为 null。
$pdo = new PDO('mysql:host=127.0.0.1;port=3306;dbname=blog_test', 'root', '');
$stmt = $pdo->prepare('SELECT * FROM zyblog_test_user');
$stmt->execute();
$stmt = null;
$pdo = null;
sleep(60);
mysqli 测试
那么应用 mysqli 的默认扩大组件,也就是应用 mysqli 对象中的 close() 来敞开数据库连贯会有这个问题吗?还是间接用代码来测试测试。(mysql 扩大曾经过期不举荐应用了,大家如果要本人封装数据库操作类或者写小 Demo 的话还是要用 mysqli 更好一些)
$conn = new mysqli('127.0.0.1', 'root', '','blog_test');
$result = $conn->query('SELECT * FROM zyblog_test_user');
$stmt = $conn->prepare("SELECT * FROM zyblog_test_user");
$stmt->execute();
$conn->close();
sleep(60);
在运行上述代码后,咱们在数据库中查看连贯过程就不会看到还在执行的连贯的,也就是说在 mysqli 中调用 close() 办法是可能间接马上敞开掉数据库的连贯的。
总结
其实明天的内容也是官网文档对于数据库连贯这一页文档上的一个 Note 中的信息。很早就有大神发现了这个问题并且分享了进去,然而大部分人基本都不晓得这个问题,甚至很多人连 PDO 也是能够敞开数据库连贯的都不晓得。框架在带给咱们便当的同时,的确也将很多货色封装的太好了,以至于很多敌人都不去关怀底层的一些内容,然而,当你向更高阶层迈进时,往往这些底层的货色会成为你的妨碍。
测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202008/source/PHP%E4%B8%ADPDO%E5%85%B3%E9%97%AD%E8%BF%9E%E6%8E%A5%E7%9A%84%E9%97%AE%E9%A2%98.php
参考文档:
https://www.php.net/manual/zh/pdo.connections.php
https://www.php.net/manual/zh/pdo.connections.php#114822
各自媒体平台均可搜寻【硬核项目经理】