繁体   English   中英

PHP oci_connect() 卡住/没有超时

[英]PHP oci_connect() stuck / no time-out

我们使用 Lumen 5.2.x (Laravel) 应用程序从 Oracle 数据库获取数据。 出于这个原因,我们使用oci_connect()连接到数据库。 (额外信息:我们使用 Oracle 即时客户端)

由于未知原因,应用程序没有响应,也不会返回任何数据。 经过很多小时的调试,我们发现它卡在了同样的方法中: oci_connect() 显然,该函数没有返回“超时”消息或任何类似的信息。

后来好像数据库转移到了别的主机上,就是连接不上的原因。 然而,我们预料到了一个错误,而不是大量的等待。

这就是我们试图强制设置超时的原因,直到现在这还没有解决。

我们尝试过的事情:

  • 将此添加到连接字符串: (CONNECT_TIMEOUT=10)(RETRY_COUNT=3)完全忽略。

  • max_execution_timeset_time_limit设置为1

  • 添加带有设置的sqlnet.ora

     TCP.CONNECT_TIMEOUT=10 SQLNET.INBOUND_CONNECT_TIMEOUT=10 SQLNET.OUTBOUND_CONNECT_TIMEOUT=10

我们尝试过的一切都失败了,有人知道如何解决这个错误吗? 任何帮助表示赞赏!

编辑:系统信息:Windows Server 2012 R2、IIS 8、PHP 5.6

下面是用于oracle的laravel包,你可以试试这个,

oracle的laravel包

我将 oracle 数组从 oracle.php 复制到 database.php 配置文件,问题就消失了。

我的 oracle.php 文件的内容:

return [
'oracle' => [
    'driver'   => 'oracle',
    'tns'      => env('DB_TNS', ''),
    'host'     => env('DB_HOST', 'localhost'),
    'port'     => env('DB_PORT', '1521'),
    'database' => env('DB_DATABASE', ''),
    'username' => env('DB_USERNAME', ''),
    'password' => env('DB_PASSWORD', ''),
    'charset'  => env('DB_CHARSET', 'AL32UTF8'),
    'prefix'   => env('DB_PREFIX', ''),
],
];

不幸的是, oci_connect已经是一个太高级的函数,不允许超时控制 - OSI 模型第 5 层,如果您认为它可以为以下内容建立会话。 我建议您在端口 1521,级别 4 上尝试fsockopen ,第 5 个参数以秒为单位设置超时。 如果 fsockopen() 返回有效资源,则继续 oci_connect() ,否则报错/抛出异常。

我今天检查了它,这是在与各种远程站点建立四个 Oracle 连接时“预检评估”的一部分。 它实际上在超时秒后放弃了!

你已经尝试了几种方法,这很好。 max_execution_time是一个不错的选择。 您可以注册关闭功能,以便您可以记录错误(如果有) - 或者做任何您需要的事情。

<?php 
function shutdown(){ 
     $error=error_get_last(); 
     if(is_null($error))   
         echo "No errors"; //or do nothing
     else 
         print_r($a); //or log it properly

 } 

register_shutdown_function('shutdown'); 

ini_set('max_execution_time',3 );//max 3 seconds

sleep(5); //just for test it out

在任何情况下,根据网络(例如: “不要松懈,转向 Linux” ),如果可能,您应该尝试在使用 Oracle 连接时使用 Linux 来运行您的网络服务器)。

(我知道在某个时候,Linux 和 Windows People 之间有很多愤怒。但如果操作系统更适合某些用例,为什么还要使用另一个)

从文档:

“有时,当从 PHP 访问时,Oracle 不会清除影子进程。为避免这种情况,请检查您的 Oracle 客户端目录中的 $ORACLE_HOME/network/admin/tnsnames.ora 文件,并删除 (SERVER=DEDICATED) 标记(如果已设置)。

要让 Oracle 在超时时删除影子进程,请在您的

$ORACLE_HOME/network/admin/sqlnet.ora

在您的 ORACLE 服务器目录中找到:

SQLNET.EXPIRE_TIME=n 

其中'n'是关闭连接之前让连接空闲的分钟数。”

你试过这个吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM