Skip to content
Permalink
Browse files

Make MSqlQuery.exec and .prepare more resiliant to disappearing MySQL

connections.  

If the database connection is down on entry, it will try to 
reconnect or fail.  

If the .exec or .prepare call fails due to "MySQL server went away" (error code
2006), it will try to reconnect, and if that works, it will retry the call once.

This should keep the frontend and backend (et al) from going absolutely crazy
if the mysql server needs to be restarted for any reason.  Previously, all
further queries would fail, requiring restarts.

Fixes #8903



git-svn-id: http://svn.mythtv.org/svn/trunk@26225 7dbf422c-18fa-0310-86e9-fd20926502f2
  • Loading branch information
Beirdo committed Sep 11, 2010
1 parent 9daad79 commit 528324d8ba5682d391a15a6f5b135009bcc4fcb7
Showing with 57 additions and 0 deletions.
  1. +56 −0 mythtv/libs/libmythdb/mythdbcon.cpp
  2. +1 −0 mythtv/libs/libmythdb/mythdbcon.h
@@ -153,6 +153,7 @@ bool MSqlDatabase::KickDatabase()
QString query("SELECT NULL;");
for (unsigned int i = 0 ; i < 2 ; ++i, usleep(50000))
{
if (m_db.isOpen())
{
QSqlQuery result = m_db.exec(query); // don't convert to MSqlQuery
if (result.isActive())
@@ -176,6 +177,17 @@ bool MSqlDatabase::KickDatabase()
return false;
}

bool MSqlDatabase::Reconnect()
{
m_db.close();
m_db.open();

bool open = m_db.isOpen();
if (open)
VERBOSE(VB_IMPORTANT, "MySQL reconnected successfully");

return open;
}

// -----------------------------------------------------------------------

@@ -463,8 +475,22 @@ MSqlQueryInfo MSqlQuery::DDCon()

bool MSqlQuery::exec()
{
// Database connection down. Try to restart it, give up if it's still
// down
if (!m_db->isOpen() && !m_db->Reconnect())
{
VERBOSE(VB_IMPORTANT, "MySQL server disconnected");
return false;
}

bool result = QSqlQuery::exec();

// if the query failed with "MySQL server has gone away"
// Close and reopen the database connection and retry the query if it
// connects again
if (!result && QSqlQuery::lastError().number() == 2006 && m_db->Reconnect())
result = QSqlQuery::exec();

if (VERBOSE_LEVEL_CHECK(VB_DATABASE))
{
QString str = lastQuery();
@@ -493,8 +519,22 @@ bool MSqlQuery::exec()

bool MSqlQuery::exec(const QString &query)
{
// Database connection down. Try to restart it, give up if it's still
// down
if (!m_db->isOpen() && !m_db->Reconnect())
{
VERBOSE(VB_IMPORTANT, "MySQL server disconnected");
return false;
}

bool result = QSqlQuery::exec(query);

// if the query failed with "MySQL server has gone away"
// Close and reopen the database connection and retry the query if it
// connects again
if (!result && QSqlQuery::lastError().number() == 2006 && m_db->Reconnect())
result = QSqlQuery::exec(query);

VERBOSE(VB_DATABASE,
QString("MSqlQuery::exec(%1) %2%3")
.arg(m_db->MSqlDatabase::GetConnectionName()).arg(query)
@@ -543,7 +583,23 @@ bool MSqlQuery::prepare(const QString& query)
//exit(1);
}
#endif

// Database connection down. Try to restart it, give up if it's still
// down
if (!m_db->isOpen() && !m_db->Reconnect())
{
VERBOSE(VB_IMPORTANT, "MySQL server disconnected");
return false;
}

bool ok = QSqlQuery::prepare(query);

// if the prepare failed with "MySQL server has gone away"
// Close and reopen the database connection and retry the query if it
// connects again
if (!ok && QSqlQuery::lastError().number() == 2006 && m_db->Reconnect())
ok = QSqlQuery::prepare(query);

if (!ok && !(GetMythDB()->SuppressDBMessages()))
{
VERBOSE(VB_IMPORTANT, QString("Error preparing query: %1").arg(query));
@@ -28,6 +28,7 @@ class MPUBLIC MSqlDatabase
bool KickDatabase(void);
QString GetConnectionName(void) const { return m_name; }
QSqlDatabase db(void) const { return m_db; }
bool Reconnect(void);

private:
QString m_name;

0 comments on commit 528324d

Please sign in to comment.
You can’t perform that action at this time.