【问题标题】:PHP oci_connect() stuck / no time-outPHP oci_connect() 卡住/没有超时
【发布时间】:2018-09-16 15:17:50
【问题描述】:

我们正在使用 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

【问题讨论】:

标签: php laravel lumen oracle-call-interface


【解决方案1】:

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

laravel package for oracle

【讨论】:

  • 谢谢,我们之前使用过这个包,但不太喜欢它(我不记得为什么)。我们可能想再检查一次!
【解决方案2】:

我将 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', ''),
],
];

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      您已经尝试了几种方法,这很棒。 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
      

      在任何情况下,根据网络(例如:"don't loose your head, move to Linux"),在使用 Oracle 连接时,您应该尝试使用 Linux 来运行您的网络服务器,如果可能的话)。

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

      【讨论】:

        【解决方案5】:

        来自文档:

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

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

        中添加以下行
        $ORACLE_HOME/network/admin/sqlnet.ora
        

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

        SQLNET.EXPIRE_TIME=n 
        

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

        你试过了吗?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-05-29
          • 2014-04-29
          • 1970-01-01
          • 1970-01-01
          • 2012-03-07
          • 2012-06-30
          相关资源
          最近更新 更多