简体   繁体   中英

Why doesn't PHP's oci_connect return false?

I have a situation in which we have two production databases that synchronize with one other. Server One is considered the primary. Sometimes due to maintenance or a disaster Server Two will become primary.

In some of our code that means we have to manually go in and edit the server name for database connections. I find this annoying, so the last thing I wrote I put the server information for both and set up a loop. If oci_connect failed on the Server One 3 times it would move on to Server Two. If Server Two failed 3 times it would notify the user a connection couldn't be made.

This has worked fine most times we've had the situation of switching the servers. Yesterday, for example, it worked fine. Today it didn't. It just sat and spun endlessly. No error in the PHP error log. No failure to move on from. No error output to the screen. Nothing for 5 minutes.

So then I had to manually edit the stupid config file.

I asked what could possibly be different and I was told "yesterday the database was down, but not the server. today the server is down." Okay...? But I don't see a distinction. I would expect oci_connect to return false if it can't establish any sort of communication with the server. I'd expect it to timeout and error. Not just pass it on when it receives an error code from the server. What if there's a network problem, for example?

Is this a bug in oci_connect or is there a possibility that something in our PHP configuration gives oci_connect a crazily long timeout?

If it is a sort of "bug" is there some way I can check to see if the server is up first? Like a ping? (Of course when I did a ping through the command prompt I got a response from Server One and then was told, "it's back now" although I am skeptical about the timing on that.)

Anyway, if anyone could shed some light on why oci_connect might run endlessly without failing and how to keep it from doing so I'd be grateful.

-- Edit: My code looks like the examples on PHP.net only in some loops.

 $count = count($servers);
 for($i = 0; $i < $count; $i++){
      if((!isset($connection)) || ($connection == false)){
           // Attempt to connect to the oracle database
           $connection = @oci_connect($servers[$i]["user"], $servers[$i]["pass"], $servers[$i]["conid"]) or ($conn_error = oracle_error());
           // Try again if there was a failure
           if(($connection == false) || (isset($con_error))){
                // Three (two more) tries per alternative
                for($j = $st; $j < $fn; $j++){
                     // Try again to connect
                     $connection = @oci_connect($servers[$i]["user"], $servers[$i]["pass"], $servers[$i]["conid"]) or ($conn_error = oracle_error());
                } // for($j = 2; $j < 4; $j++)
           } // if($connection == false)
      } // if(!isset($connection) || ($connection == false))
 } // for($i = 0; $i < $count; $i++)

Can you verify that it's not returning false? Is it perhaps just blocking while waiting for a connection? (what happens if you do var_dump(oci_connect(...)) ?

Right from php.net's documentation :

If you want to specify a connection timeout in case there is network problem, you can edit the client side (eg PHP side) sqlnet.ora file and set SQLNET.OUTBOUND_CONNECT_TIMEOUT. This sets the upper time limit for establishing a connection right through to the DB, including the time for attempts to connect to other services. It is available from Oracle 10.2.0.3 onwards.

In Oracle 11.1, a slightly lighter-weight solution TCP.CONNECT_TIMEOUT was introduced. It also is a sqlnet.ora parameter. It bounds just the TCP connection establishment time, which is mostly where connection problem are seen.

The client sqlnet.ora file should be put in the same directory as the tnsnames.ora file.

Also, you may want to check out FAN on this page ... It looks like it may do exactly what you want (but I have no experience with it, so I'm not sure if it's really right for you).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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