Re: [PDO] PostgreSQL auto-reconnect in PDO contructor for permanent connections: request for comments

[email protected] (Marc Barilley) Wed, 31 Mar 2010 12:27:40 +0200
Newsgroups php.pdo
Message-ID <[email protected]>
Christopher Jones a écrit :
>
>
> On 03/30/2010 04:01 PM, Joey Smith wrote:
>> On Tue, Mar 30, 2010 at 02:48:47PM -0700, Christopher Jones wrote:
>>>
>>>
>>> Joey Smith wrote:
>>>> On Tue, Mar 30, 2010 at 05:50:29PM +0200, Marc Barilley wrote:
>>>>> This is something I'd like to add in the PostgreSQL driver. In
>>>>> order not
>>>>> to break anything in the current implementation, my idea was to add a
>>>>> driver specific constant (named PGSQL_ATTR_DEEP_CONNECTION_CHECK for
>>>>> example, or anything that fits) that would make the driver run a
>>>>> "SELECT
>>>>> 1" when retrieving a connection link from the pool to re-use it:
>>>>> if the
>>>>> connection is actually broken, it would then be re-opened by the
>>>>> subsequent code. The default would be keeping the way it works now.
>>>>> Does this seem reasonnable?
>>>>>
>>>>> Thank you for your comments.
>>>>
>>>> I'm +1 on the idea, and suggest 'PDO::ATTR_PGSQL_PING' as the
>>>> constant name.
>>>>
>>>
>>> -1 on a PG specific attribute.  But +0 on a generic PDO solution.
>>>
>>> The approach gives an appearance of reliability and removes
>>> scalability.
>>>
>>> Ultimately any SQL statement that actually uses a connection must
>>> check for failures, because the network or database might have failed
>>> in the time between the PHP connect call and the execution of the
>>> statement.
>>>
>>> For reference, OCI8 has a parameter oci8.ping_interval.  From php.ini:
>>>
>>>    ; Connection: The number of seconds that must pass before issuing a
>>>    ; ping during oci_pconnect() to check the connection validity. When
>>>    ; set to 0, each oci_pconnect() will cause a ping. Using -1 disables
>>>    ; pings completely.
>>>    ; http://php.net/oci8.ping-interval
>>>    ;oci8.ping_interval = 60
>>>
>>> I generally recommend setting it to -1, detecting SQL errors, and then
>>> reconnecting if appropriate.
>>>
>>> Chris
>>
>> Perhaps I misunderstood - I thought the underlying problem he was
>> trying to
>> fix is that in certain cases, PQstatus() doesn't throw an error, even
>> though
>> the connection has actually gone away?
>
> That's very similar to the case that oci8.ping_interval was created
> for.  Persistent connections (oci_pconnect) can be held open for days.
> If the DB is restarted (invalidating the connection data structure
> cached in PHP) the only time PHP knows about the restart is when the
> first SQL statement generates an error.  In this scenario setting
> oci8.ping_interval would allow PHP OCI8 to detect and reconnect
> transparently so the script wouldn't see an error.  This has the
> availability & scalability caveats I mentioned previously.
>
> Recent OCI8 code handles this better and can reconnect automatically
> in some cases without the overhead of a ping, but that's getting off
> topic.
>
>> If that's true, we definitely should do SOMETHING to fix it - if you
>> can't
>> know that the connection went away, it's pretty hard to handle that
>> on the
>> userspace side.
>>
>> As for it being PgSQL specific, I could go either way, I suppose -
>> PDO::ATTR_PING_CONNECTION?
>
> It would be more flexible, aka better for other drivers, to allow a
> variable time interval.
>
> Chris
>

I went to the wiki and saw this paragraph about persistent connections,
proposing to allow to disable certain connection reset/cleanup features.
Then maybe the approach should be the opposite than what I proposed:
always perform a "SELECT 1" on the connection and add a driver specific
constant to disable this. This is a fair proposal, considering that the
average programmer expects such magic from the driver while the expert
one, namely the one who targets performance and the rest, has a better
knowledge of his tools and may -- or may not -- want to use this
feature. Then the default behaviour would be that "PDO::ATTR_PGSQL_PING"
be set to true (or the driver would behave like so) and one could
disable this feature by setting the option to false. I could even add
this mechanism to the MySQL driver, when I have time.
Maybe OCI8 could use a "PDO::ATTR_OCI_PING_INTERVAL" or something that
would set the time interval between pings? That way, both drivers could
implement their own way of handling connections recycling without
interfering with each other. But using a time interval in the PostgreSQL
driver is beyond the scope of the modification I propose...

Marc