Skip to content

Commit

Permalink
Bug #943031 MySQL Server has gone away
Browse files Browse the repository at this point in the history
added docnotes of error messages caught for mysql and reference

Change-Id: I147b32193436be891e54e36c6adc1b16fda886d3
  • Loading branch information
pubyun authored and heckj committed Mar 13, 2012
1 parent 97460ef commit e65a22c
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 4 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Expand Up @@ -72,6 +72,7 @@ Michael Still <mikal@stillhq.com>
Monty Taylor <mordred@inaugust.com>
Pádraig Brady <P@draigBrady.com>
Paul Voccio <paul@substation9.com>
Peng Yong <ppyy@pubyun.com>
Pete Zaitcev <zaitcev@kotori.zaitcev.us>
Ralf Haferkamp <rhafer@suse.de>
Ramana Juvvadi <ramana@venus.lekha.org>
Expand Down
43 changes: 39 additions & 4 deletions keystone/common/sql/core.py
Expand Up @@ -22,12 +22,14 @@
import eventlet.db_pool
import sqlalchemy as sql
from sqlalchemy import types as sql_types
from sqlalchemy.exc import DisconnectionError
from sqlalchemy.ext import declarative
import sqlalchemy.orm
import sqlalchemy.pool
import sqlalchemy.engine.url

from keystone import config
from keystone.common import logging


CONF = config.CONF
Expand All @@ -45,6 +47,7 @@

# Special Fields
class JsonBlob(sql_types.TypeDecorator):

impl = sql.Text

def process_bind_param(self, value, dialect):
Expand All @@ -55,6 +58,7 @@ def process_result_value(self, value, dialect):


class DictBase(object):

def to_dict(self):
return dict(self.iteritems())

Expand Down Expand Up @@ -94,8 +98,39 @@ def iteritems(self):
#return local.iteritems()


class MySQLPingListener(object):

"""
Ensures that MySQL connections checked out of the
pool are alive.
Borrowed from:
http://groups.google.com/group/sqlalchemy/msg/a4ce563d802c929f
Error codes caught:
* 2006 MySQL server has gone away
* 2013 Lost connection to MySQL server during query
* 2014 Commands out of sync; you can't run this command now
* 2045 Can't open shared memory; no answer from server (%lu)
* 2055 Lost connection to MySQL server at '%s', system error: %d
from http://dev.mysql.com/doc/refman/5.6/en/error-messages-client.html
"""

def checkout(self, dbapi_con, con_record, con_proxy):
try:
dbapi_con.cursor().execute('select 1')
except dbapi_con.OperationalError, ex:
if ex.args[0] in (2006, 2013, 2014, 2045, 2055):
logging.warn('Got mysql server has gone away: %s', ex)
raise DisconnectionError("Database server went away")
else:
raise


# Backends
class Base(object):

_MAKER = None
_ENGINE = None

Expand All @@ -108,14 +143,11 @@ def get_session(self, autocommit=True, expire_on_commit=False):
expire_on_commit)

session = self._MAKER()
# TODO(termie): we may want to do something similar
#session.query = nova.exception.wrap_db_error(session.query)
#session.flush = nova.exception.wrap_db_error(session.flush)
return session

def get_engine(self):
"""Return a SQLAlchemy engine."""
connection_dict = sqlalchemy.engine.url.make_url(CONF.sql.connection)
connection_dict = sql.engine.url.make_url(CONF.sql.connection)

engine_args = {'pool_recycle': CONF.sql.idle_timeout,
'echo': False,
Expand All @@ -125,6 +157,9 @@ def get_engine(self):
if 'sqlite' in connection_dict.drivername:
engine_args['poolclass'] = sqlalchemy.pool.NullPool

if 'mysql' in connection_dict.drivername:
engine_args['listeners'] = [MySQLPingListener()]

return sql.create_engine(CONF.sql.connection, **engine_args)

def get_maker(self, engine, autocommit=True, expire_on_commit=False):
Expand Down

0 comments on commit e65a22c

Please sign in to comment.