正确关闭PHP PDO连接,不能正常工作


FreeTDS: Properly close a PHP PDO connection, not working correctly

我有一个旧的CodeIgniter实例,我试图使用PHP PDO。这是基于"点击"修改(见下面的链接)。它在小的请求负载下工作得很好,但是在大的请求负载下,连接似乎挂起了很长时间。最后,我用完了可用的连接,数据库返回错误:SQLSTATE[] (null)(严重性0)。

https://github.com/cickes/PDOinCodeigniter2

我使用的是MS SQL Server 2008与PHP PDO。MSSQL的PHP驱动程序是FreeTDS驱动程序,可以从phpinfo()输出中看到。freeds PHPINFO如下所示:

mssql
MSSQL Support   enabled
Active Persistent Links 1
Active Links    1
Library version FreeTDS
Directive   Local Value Master Value
mssql.allow_persistent  On  On
mssql.batchsize 0   0
mssql.charset   no value    no value
mssql.compatability_mode    Off Off
mssql.connect_timeout   5   5
mssql.datetimeconvert   On  On
mssql.max_links Unlimited   Unlimited
mssql.max_persistent    Unlimited   Unlimited
mssql.max_procs Unlimited   Unlimited
mssql.min_error_severity    10  10
mssql.min_message_severity  10  10
mssql.secure_connection Off Off
mssql.textlimit Server default  Server default
mssql.textsize  Server default  Server default
mssql.timeout   60  60

我已经将DB处理程序设置为空,并将DB处理程序unset()设置为空。这两种变化都无济于事。最后我用完了连接。

我认为我可以尝试在连接期间传递属性选项,就像PHP网站上建议的那样。不幸的是,FreeTDS驱动程序不支持属性。第一个定义的$DB是工作的,但我相信它使用持久连接。

$DB = new PDO($params['dbdriver'].':host='.$params['hostname'].'; dbname='.$params['database'], $params['username'], $params['password']);

注意:驱动程序不支持下面的属性设置示例。

$DB = new PDO($params['dbdriver'].':host='.$params['hostname'].'; dbname='.$params['database'], $params['username'], $params['password'], array(
    PDO::ATTR_PERSISTENT => false
));

日志信息:PDO::__construct(): SQLSTATE[IM001]: Driver does not support this function: Driver does not support setting attributes

$ DB =新PDO (params [' dbdriver ']美元。":主机= '。美元params['主机']。';dbname = '。params["数据库"],美元params["用户名"],美元params['密码']);

PDO::__construct(): SQLSTATE[IM001]: Driver does not support this function: Driver does not support setting attributes.

可能是持久链接导致了问题?我认为在这个服务器上也使用了非持久的mssql_connect()函数。也许有人可以建议一个更好的配置为FreeTDS驱动程序?

Laravel测试(添加08/14/2014):

我决定在"同一台服务器"上使用相同的数据库连接设置测试Laravel。它不会产生同样的问题。我可以连续多次击中它而不会"挂起"或DB错误。所以,这就带来了一个问题:Laravel做PHP PDO有什么不同?

CodeIgniter的循环PDO更改包含我发现的一个错误。DB函数被多次调用,因此数据库连接被多次调用(9)。为了防止这种情况,我首先检查对全局DB变量的引用,以确保我没有创建到数据库的另一个连接。我希望这个答案能帮助到其他可能遇到同样问题的人。

参见Github Project:

https://github.com/cickes/PDOinCodeigniter2

文件:

https://github.com/cickes/PDOinCodeigniter2/blob/master/system/database/DB.php

if (!empty($GLOBALS['DB'])) $DB = $GLOBALS['DB'];
//var_dump($DB);
//echo "DB Function Called."."<br />";
if (empty($DB)) {
// Using PDO: connect to a database using PDO
try {
    echo "Creating new PDO Connection!";
    $DB = new PDO($params['dbdriver'].':host='.$params['hostname'].'; dbname='.$params['database'], $params['username'], $params['password']);
    if (ENVIRONMENT == 'development') {
        $DB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    } elseif (ENVIRONMENT == 'production') {
        $DB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
    }
    $DB->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL);
    $DB->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_NATURAL);
    $DB->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
    //$DB->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    $GLOBALS['DB'] = $DB;
} catch(PDOException $e) {
    //print_r($params);
    echo $e->getMessage();
}
}

尝试重用连接,如果可能的话,不要自己关闭它们(PDO足够聪明,可以这样做)。

创建新连接前检查连接是否为null

if($DB == null){
    $DB = new PDO($params['dbdriver'].':host='.$params['hostname'].'; dbname='.$params['database'], $params['username'], $params['password']);
    $DB->setAttribute(PDO::ATTR_PERSISTENT, false);    
}