Mysql::Prepare() doesn't recover from MySQL connection going away

Create issue
Issue #130 resolved
Ben Smith created an issue

By default, MySQL closes inactive connections after 8 hours. Mysql::Exec() gracefully handles this and reconnects, but Mysql::Prepare() does not. mhttpd uses prepared statements when creating history plots, so this is easily encountered (no plots are rendered until mhttpd is restarted).

Mysql::Exec() has the ability to buffer many queries, but that seems less important for Mysql::Prepare(), which isn't used as widely.

My suggestion is to change this section in history_schema.cxx:1149:

   if (mysql_query(fMysql, sql)) {
      cm_msg(MERROR, "Mysql::Prepare", "mysql_query(%s) error %d (%s)", sql, mysql_errno(fMysql), mysql_error(fMysql));
      return DB_FILE_ERROR;
   }

to

   int status = mysql_query(fMysql, sql);
   if (status) {
      if (mysql_errno(fMysql) == 2006 || mysql_errno(fMysql) == 2013) {
         // "MySQL server has gone away" or "Lost connection to MySQL server during query"
         status = Connect(fConnectString.c_str());
         if (status == DB_SUCCESS) {
            // Retry after reconnecting
            status = mysql_query(fMysql, sql);
         } else {
            cm_msg(MERROR, "Mysql::Prepare", "mysql_query(%s) - MySQL server has gone away, and couldn't reconnect - %d", sql, status);
            return DB_FILE_ERROR;
         }
      }
      if (status) {
         cm_msg(MERROR, "Mysql::Prepare", "mysql_query(%s) error %d (%s)", sql, mysql_errno(fMysql), mysql_error(fMysql));
         return DB_FILE_ERROR;
      }
   }

Comments (2)

  1. Log in to comment