Re: [Zope3-dev] Re: rdb: Disappearing Connection

2006-01-13 Thread Brian Sutherland
Hi,

Thanks for posting this, it saved me quite a few hours.

On Fri, Dec 16, 2005 at 04:23:36PM -0500, Jim Washington wrote:
> def isConnected(self):
> try:
> self._v_connection.ping()
> except:
> # not connected or ping did not restore MySQL connection
> if self._v_connection is not None:
> self._v_connection.close()
> self._v_connection = None
> return False
> return True

I have two comments that I noticed:

* If the connection was closed directly, by something else, you can fail
  when you try to close the connection:

File "/home/jinty/src/Z3/z3/src/mysqldbda/adapter.py", line 87, in 
isConnected
self._v_connection.close()
ProgrammingError: closing a closed connection

  Which means that _v_connection will not be set to None and it will
  carry on failing.

* Also, if, in this transaction, some SQL has been sent through the
  connection, the connection will have registered itself with the
  transaction manager. This made both aborting and commiting the
  transaction fail for me.

-- 
Brian Sutherland

Metropolis - "it's the first movie with a robot. And she's a woman.
  And she's EVIL!!"
___
Zope3-dev mailing list
Zope3-dev@zope.org
Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com



Re: [Zope3-dev] Re: rdb: Disappearing Connection

2005-12-27 Thread Dieter Maurer
Jim Washington wrote at 2005-12-16 16:23 -0500:
> ...
>What seems to work for me now is the following as 
>mysqldbda.adapter.MySQLdbAdapter.isConnected()
>
>def isConnected(self):
>try:
>self._v_connection.ping()
>except:
># not connected or ping did not restore MySQL connection
>if self._v_connection is not None:
>self._v_connection.close()
>self._v_connection = None
>return False
>return True
>
>I am not well-versed in the intricacies of conflictError, so what else 
>should happen here?  I do not see how there would be unresolved 
>transactions remaining, and the connection I need is now available or 
>soon will be established.

"isConnected" is fine as you cite it above.

However, the action taken (by the caller) when "isConnected" returns
"False" might be wrong. Reopening and then
using the connection in this case is safe only
when the connection was not yet used before in this same transaction.

-- 
Dieter
___
Zope3-dev mailing list
Zope3-dev@zope.org
Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com



Re: [Zope3-dev] Re: rdb: Disappearing Connection

2005-12-16 Thread Jim Washington

Dieter Maurer wrote:


Jim Washington wrote at 2005-12-13 21:40 -0500:
 


...
Now, looking closer at the code, a ping like this might be not too bad, 
because isConnected() is only called when a connection is requested, not 
for every SQL statement executed.  So, it might not be so onerous as 
originally thought. Still not ideal, though.
   



Be careful what you do when you find that "isConnected()" returns false.
Note, that, in general, it would be a bug to just reopen a new connection
in this case: previous operations against the connection might have
been lost without notice when you simply reopen a new connection
and do as if nothing bad had happened.
Instead, you should reopen the connection and then raise an exception
similar to "ZODB.POSException.ConflictError". Hopefully, the publisher
will handle this kind of exception correctly (by retrying the complete
request).

 


Thanks, Dieter.

The situation I wish to handle is the case where MySQL server silently 
closes its connection with Zope after 8 hours idle, which likely will 
happen at least once a day.


What seems to work for me now is the following as 
mysqldbda.adapter.MySQLdbAdapter.isConnected()


def isConnected(self):
   try:
   self._v_connection.ping()
   except:
   # not connected or ping did not restore MySQL connection
   if self._v_connection is not None:
   self._v_connection.close()
   self._v_connection = None
   return False
   return True

I am not well-versed in the intricacies of conflictError, so what else 
should happen here?  I do not see how there would be unresolved 
transactions remaining, and the connection I need is now available or 
soon will be established.


In the current rdb implementation, isConnected() is not called for each 
SQL statement.  It is only called when the utility is called.


e.g.,

conn = zapi.getUtility(IZopeDatabaseAdapter, 'spam') #isConnected has 
not been called yet

db = conn() #here, isConnected() gets called
c = db.cursor() #isConnected() is not called
c.execute('SELECT 1') #isConnected() is not called

-Jim Washington
___
Zope3-dev mailing list
Zope3-dev@zope.org
Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com



Re: [Zope3-dev] Re: rdb: Disappearing Connection

2005-12-15 Thread Velko Ivanov



jürgen Kartnaller wrote:


MySQL::Ping will automatically reopen a closed connection in a way where
the existing connection object can still be used.
If MySQL::Ping fails something really bad is going on.

To reduce the number of ping's in my application I used a timer which
was tested before every call to a database function.
If the timer expired I did a ping to ensure mysql is reconnected.


This is the code sqlobject is using :

while (1):
try:
   return cursor.execute(query)
except MySQLdb.OperationalError, e:
   if e.args[0] == 2013: # SERVER_LOST error
   if self.debug:
   self.printDebug(conn, str(e), 'ERROR')
   else:
  raise

So, checking for SERVER_LOST and then eventually using MySQL::Ping would
do the trick.


Jürgen




Sorry if that is mentioned somewhere, I missed the begining of the 
thread, but I just want to add, that MySQL is not the only SQL server in 
use. And this particular problem is not MySQL specific - I'm having 
troubles with disappearing connections with PostgreSQL, which doesn't 
have MySQL::Ping. The patch, that was proposed already - use a SELECT 
statement to ensure the connection is available - is not the best 
solution at least in my case, because my code never dares to store, or 
reuse a connection, knowing that connections are being managed by Zope 
(with a volatile attribute) and this turns into one getConnection() call 
per request.
I was thinking about handling exceptions, because it does generate 
exception at the end and I know I need to reconnect when I see it in the 
log (restart the server actually, because I authenticate trough the SQL 
database).
I do hope however that I will be able to configure the SQL server in a 
way to prevent the connection from dissappearing at all, when the time 
comes to solve this problem.



Regards
Velko Ivanov
___
Zope3-dev mailing list
Zope3-dev@zope.org
Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com



Re: [Zope3-dev] Re: rdb: Disappearing Connection

2005-12-15 Thread Dieter Maurer
Jim Washington wrote at 2005-12-13 21:40 -0500:
> ...
>Now, looking closer at the code, a ping like this might be not too bad, 
>because isConnected() is only called when a connection is requested, not 
>for every SQL statement executed.  So, it might not be so onerous as 
>originally thought. Still not ideal, though.

Be careful what you do when you find that "isConnected()" returns false.
Note, that, in general, it would be a bug to just reopen a new connection
in this case: previous operations against the connection might have
been lost without notice when you simply reopen a new connection
and do as if nothing bad had happened.
Instead, you should reopen the connection and then raise an exception
similar to "ZODB.POSException.ConflictError". Hopefully, the publisher
will handle this kind of exception correctly (by retrying the complete
request).

-- 
Dieter
___
Zope3-dev mailing list
Zope3-dev@zope.org
Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com



Re: [Zope3-dev] Re: rdb: Disappearing Connection

2005-12-14 Thread Jim Washington

jürgen Kartnaller wrote:


Without going much deeper into the way zope uses database connections.

Wouldn't MySQL:Ping solve the reconnect Problem.
That's what I used in my old C++ projects.
Some kind of "ensureConnected" at the right place.

Jürgen
 


Thanks! I'll look into it.

-Jim Washington
___
Zope3-dev mailing list
Zope3-dev@zope.org
Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com



Re: [Zope3-dev] Re: rdb: Disappearing Connection

2005-12-13 Thread Jim Washington

Jim Washington wrote:


Florent Guillaume wrote:


Jim Washington wrote:

Spelunking a bit in the code, 
zope.app.rdb.ZopeDatabaseAdapter.isConnected() looks at whether 
_v_connection is present, not whether the connection is actually 
alive.  If we fix this here, isConnected() perhaps should handle the 
case where the connection might be reaped by the back end db.




Frankly anything that uses _v_ attributes is asking for trouble 
because it relies on low level behaviour of the ZODB and persistence 
mechanisms. They can disappear at unpredictable times. Avoid them.



Hi, Florent

In this case, it is not particulary a problem if the _v_ attribute is 
not there.  It gets recreated if it does not exist.  It is designed 
this way so that different zope threads get separate rdb connections, 
which is good.  The problem here is false positives, where the _v_ 
attribute exists, but the connection it promises has been silently 
expired and disconnected by the MySQL server.


I was thinking of a check in isConnected() by making a cursor then 
"try"ing executing "select 1" and return True if it does not raise the 
exception.  But that would be bad because it ~doubles the number of 
requests to the SQL server. Perhaps not smart.


Now, looking closer at the code, a ping like this might be not too bad, 
because isConnected() is only called when a connection is requested, not 
for every SQL statement executed.  So, it might not be so onerous as 
originally thought. Still not ideal, though.


-Jim Washington
___
Zope3-dev mailing list
Zope3-dev@zope.org
Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com