bool MySQLConnection::_Query(PreparedStatement* stmt, MYSQL_RES **pResult, uint64* pRowCount, uint32* pFieldCount) { if (!m_Mysql) return false; uint32 index = stmt->m_index; { MySQLPreparedStatement* m_mStmt = GetPreparedStatement(index); ASSERT(m_mStmt); // Can only be null if preparation failed, server side error or bad query m_mStmt->m_stmt = stmt; // Cross reference them for debug output stmt->m_stmt = m_mStmt; // TODO: Cleaner way stmt->BindParameters(); MYSQL_STMT* msql_STMT = m_mStmt->GetSTMT(); MYSQL_BIND* msql_BIND = m_mStmt->GetBind(); uint32 _s = 0; if (sLogMgr->IsLogEnabled(SQLDRIVER_LOG)) _s = getMSTime(); if (mysql_stmt_bind_param(msql_STMT, msql_BIND)) { uint32 lErrno = mysql_errno(m_Mysql); sLogMgr->WriteLn(SQLDRIVER_LOG, "SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT)); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) return _Query(stmt, pResult, pRowCount, pFieldCount); // Try again m_mStmt->ClearParameters(); return false; } if (mysql_stmt_execute(msql_STMT)) { uint32 lErrno = mysql_errno(m_Mysql); sLogMgr->WriteLn(SQLDRIVER_LOG, "SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT)); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) return _Query(stmt, pResult, pRowCount, pFieldCount); // Try again m_mStmt->ClearParameters(); return false; } if (sLogMgr->IsLogEnabled(SQLDRIVER_LOG)) sLogMgr->WriteLn(SQLDRIVER_LOG, "[%u ms] SQL(p): %s", getMSTimeDiff(_s, getMSTime()), m_mStmt->getQueryString(m_queries[index].first).c_str()); m_mStmt->ClearParameters(); *pResult = mysql_stmt_result_metadata(msql_STMT); *pRowCount = mysql_stmt_num_rows(msql_STMT); *pFieldCount = mysql_stmt_field_count(msql_STMT); return true; } }
bool MySQLConnection::Execute(PreparedStatement* stmt) { if (!m_Mysql) return false; uint32 index = stmt->m_index; { MySQLPreparedStatement* m_mStmt = GetPreparedStatement(index); ASSERT(m_mStmt); // Can only be null if preparation failed, server side error or bad query m_mStmt->m_stmt = stmt; // Cross reference them for debug output stmt->m_stmt = m_mStmt; // TODO: Cleaner way stmt->BindParameters(); MYSQL_STMT* msql_STMT = m_mStmt->GetSTMT(); MYSQL_BIND* msql_BIND = m_mStmt->GetBind(); uint32 _s = 0; if (sLog->GetSQLDriverQueryLogging()) _s = getMSTime(); if (mysql_stmt_bind_param(msql_STMT, msql_BIND)) { uint32 lErrno = mysql_errno(m_Mysql); sLog->outSQLDriver("[ERROR]: PreparedStatement (id: %u, database: `%s`) error binding params: [%u] %s", index, m_connectionInfo.database.c_str(), lErrno, mysql_stmt_error(msql_STMT)); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled succesfuly (ie reconnection) return Execute(stmt); // Try again m_mStmt->ClearParameters(); return false; } if (mysql_stmt_execute(msql_STMT)) { uint32 lErrno = mysql_errno(m_Mysql); sLog->outSQLDriver("[ERROR]: PreparedStatement (id: %u, database: `%s`) error executing: [%u] %s", index, m_connectionInfo.database.c_str(), lErrno, mysql_stmt_error(msql_STMT)); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled succesfuly (ie reconnection) return Execute(stmt); // Try again m_mStmt->ClearParameters(); return false; } if (sLog->GetSQLDriverQueryLogging()) sLog->outSQLDriver("[%u ms] Prepared SQL: %u on database `%s`", getMSTimeDiff(_s, getMSTime()), index, m_connectionInfo.database.c_str()); m_mStmt->ClearParameters(); return true; } }
bool MySQLConnection::Execute(PreparedStatement* stmt) { if (!m_Mysql) return false; uint32 index = stmt->m_index; { MySQLPreparedStatement* m_mStmt = GetPreparedStatement(index); /*ASSERT*/(m_mStmt); // Can only be null if preparation failed, server side error or bad query m_mStmt->m_stmt = stmt; // Cross reference them for debug output stmt->m_stmt = m_mStmt; // TODO: Cleaner way stmt->BindParameters(); MYSQL_STMT* msql_STMT = m_mStmt->GetSTMT(); MYSQL_BIND* msql_BIND = m_mStmt->GetBind(); uint32 _s = 0; if (sLog->GetSQLDriverQueryLogging()) _s = getMSTime(); if (mysql_stmt_bind_param(msql_STMT, msql_BIND)) { uint32 lErrno = mysql_errno(m_Mysql); sLog->outSQLDriver("SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT)); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) return Execute(stmt); // Try again m_mStmt->ClearParameters(); return false; } if (mysql_stmt_execute(msql_STMT)) { uint32 lErrno = mysql_errno(m_Mysql); sLog->outSQLDriver("SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT)); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) return Execute(stmt); // Try again m_mStmt->ClearParameters(); return false; } if (sLog->GetSQLDriverQueryLogging()) sLog->outSQLDriver("[%u ms] SQL(p): %s", getMSTimeDiff(_s, getMSTime()), m_mStmt->getQueryString(m_queries[index].first).c_str()); m_mStmt->ClearParameters(); return true; } }
bool MySqlConnection::_Query(PreparedStmt* stmt, MYSQL_RES **pResult, uint64* pRowCount, uint32* pFieldCount) { if (!m_Mysql) return false; uint32 index = stmt->m_stmtIndex; { MySqlPreparedStmt* pStmt = GetPreparedStatement(index); pStmt->m_pPrepareStmt = stmt; // Cross reference them for debug output stmt->m_pStmt = pStmt; /// @todo Cleaner way stmt->bindParameters(); MYSQL_STMT* msql_STMT = pStmt->GetMySqlStmt(); MYSQL_BIND* msql_BIND = pStmt->GetBind(); if (mysql_stmt_bind_param(msql_STMT, msql_BIND)) { uint32 lErrno = mysql_errno(m_Mysql); ERROR_LOG("SQL(p): %s\n [ERROR]: [%u] %s\n", pStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT)); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) return _Query(stmt, pResult, pRowCount, pFieldCount); // Try again pStmt->clearParameters(); return false; } TRACE_LOG("Exe SQL(p): %s\n\n", pStmt->getQueryString(m_queries[index].first).c_str()); if (mysql_stmt_execute(msql_STMT)) { uint32 lErrno = mysql_errno(m_Mysql); ERROR_LOG("SQL(p): %s\n [ERROR]: [%u] %s\n", pStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT)); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) return _Query(stmt, pResult, pRowCount, pFieldCount); // Try again pStmt->clearParameters(); return false; } pStmt->clearParameters(); *pResult = mysql_stmt_result_metadata(msql_STMT); *pRowCount = mysql_stmt_num_rows(msql_STMT); *pFieldCount = mysql_stmt_field_count(msql_STMT); return true; } }
bool MySQLConnection::Execute(PreparedStatement* stmt) { if (!m_Mysql) return false; uint32 index = stmt->m_index; { MySQLPreparedStatement* m_mStmt = GetPreparedStatement(index); ASSERT(m_mStmt); // Can only be null if preparation failed, server side error or bad query m_mStmt->m_stmt = stmt; // Cross reference them for debug output stmt->m_stmt = m_mStmt; /// @todo Cleaner way stmt->BindParameters(); MYSQL_STMT* msql_STMT = m_mStmt->GetSTMT(); MYSQL_BIND* msql_BIND = m_mStmt->GetBind(); boost::timer _s; if (mysql_stmt_bind_param(msql_STMT, msql_BIND)) { uint32 lErrno = mysql_errno(m_Mysql); _LOG_ERROR(LOG_FILTER_SQL, "SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT)); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) return Execute(stmt); // Try again m_mStmt->ClearParameters(); return false; } if (mysql_stmt_execute(msql_STMT)) { uint32 lErrno = mysql_errno(m_Mysql); _LOG_ERROR(LOG_FILTER_SQL, "SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT)); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) return Execute(stmt); // Try again m_mStmt->ClearParameters(); return false; } _LOG_DEBUG(LOG_FILTER_SQL, "[%u ms] SQL(p): %s",(uint32)_s.elapsed(), m_mStmt->getQueryString(m_queries[index].first).c_str()); m_mStmt->ClearParameters(); return true; } }
bool MySQLConnection::Execute(const char* sql) { if (!m_Mysql) return false; { uint32 _s = 0; if (sLog->GetSQLDriverQueryLogging()) _s = getMSTime(); if (mysql_query(m_Mysql, sql)) { uint32 lErrno = mysql_errno(m_Mysql); sLog->outSQLDriver("SQL: %s", sql); sLog->outSQLDriver("ERROR: [%u] %s", lErrno, mysql_error(m_Mysql)); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) return Execute(sql); // Try again return false; } else if (sLog->GetSQLDriverQueryLogging()) { sLog->outSQLDriver("[%u ms] SQL: %s", getMSTimeDiff(_s, getMSTime()), sql); } } return true; }
bool MySQLConnection::Execute(char const* sql) { if (!m_Mysql) return false; { uint32 _s = getMSTime(); if (mysql_query(m_Mysql, sql)) { uint32 lErrno = mysql_errno(m_Mysql); TC_LOG_INFO("sql.sql", "SQL: %s", sql); TC_LOG_ERROR("sql.sql", "[%u] %s", lErrno, mysql_error(m_Mysql)); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) return Execute(sql); // Try again return false; } else TC_LOG_DEBUG("sql.sql", "[%u ms] SQL: %s", getMSTimeDiff(_s, getMSTime()), sql); } return true; }
bool MySQLConnection::Execute(const char* sql) { if (!m_Mysql) return false; { uint32 _s = 0; if (sLogMgr->IsLogEnabled(SQLDRIVER_LOG)) _s = getMSTime(); if (mysql_query(m_Mysql, sql)) { uint32 lErrno = mysql_errno(m_Mysql); sLogMgr->WriteLn(SQLDRIVER_LOG, "SQL: %s", sql); sLogMgr->WriteLn(SQLDRIVER_LOG, "ERROR: [%u] %s", lErrno, mysql_error(m_Mysql)); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) return Execute(sql); // Try again return false; } else if (sLogMgr->IsLogEnabled(SQLDRIVER_LOG)) { sLogMgr->WriteLn(SQLDRIVER_LOG, "[%u ms] SQL: %s", getMSTimeDiff(_s, getMSTime()), sql); } } return true; }
bool MySqlConnection::_Query(const char *sql, MYSQL_RES **pResult, MYSQL_FIELD **pFields, uint64* pRowCount, uint32* pFieldCount) { if (!m_Mysql) return false; { if (mysql_query(m_Mysql, sql)) { uint32 lErrno = mysql_errno(m_Mysql); TRACE_LOG("SQL: %s\n", sql); ERROR_LOG("[%u] %s\n", lErrno, mysql_error(m_Mysql)); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) return _Query(sql, pResult, pFields, pRowCount, pFieldCount); // We try again return false; } *pResult = mysql_store_result(m_Mysql); *pRowCount = mysql_affected_rows(m_Mysql); *pFieldCount = mysql_field_count(m_Mysql); } if (!*pResult ) return false; if (!*pRowCount) { mysql_free_result(*pResult); return false; } *pFields = mysql_fetch_fields(*pResult); return true; }
bool MySQLConnection::Execute(const char* sql) { if (!m_Mysql) return false; { uint32 _s = getMSTime(); if (mysql_query(m_Mysql, sql)) { uint32 lErrno = mysql_errno(m_Mysql); sLog->outInfo(LOG_FILTER_SQL, "SQL: %s", sql); sLog->outError(LOG_FILTER_SQL, "[%u] %s", lErrno, mysql_error(m_Mysql)); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) return Execute(sql); // Try again return false; } else sLog->outDebug(LOG_FILTER_SQL, "[%u ms] SQL: %s", getMSTimeDiff(_s, getMSTime()), sql); } return true; }
bool MySQLConnection::Execute(const char* sql) { if (!m_Mysql) return false; { boost::timer _s; if (mysql_query(m_Mysql, sql)) { uint32 lErrno = mysql_errno(m_Mysql); _LOG_INFO(LOG_FILTER_SQL, "SQL: %s", sql); _LOG_ERROR(LOG_FILTER_SQL, "[%u] %s", lErrno, mysql_error(m_Mysql)); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) return Execute(sql); // Try again return false; } else _LOG_DEBUG(LOG_FILTER_SQL, "[%u ms] SQL: %s",(uint32) _s.elapsed(), sql); } return true; }
bool MySQLConnection::_HandleMySQLErrno(uint32 errNo) { switch (errNo) { case CR_SERVER_GONE_ERROR: case CR_SERVER_LOST: case CR_INVALID_CONN_HANDLE: case CR_SERVER_LOST_EXTENDED: { m_reconnecting = true; uint64 oldThreadId = mysql_thread_id(GetHandle()); mysql_close(GetHandle()); if (this->Open()) // Don't remove 'this' pointer unless you want to skip loading all prepared statements.... { sLog->outInfo(LOG_FILTER_SQL, "Connection to the MySQL server is active."); if (oldThreadId != mysql_thread_id(GetHandle())) sLog->outInfo(LOG_FILTER_SQL, "Successfully reconnected to %s @%s:%s (%s).", m_connectionInfo.database.c_str(), m_connectionInfo.host.c_str(), m_connectionInfo.port_or_socket.c_str(), (m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous"); m_reconnecting = false; return true; } uint32 lErrno = mysql_errno(GetHandle()); // It's possible this attempted reconnect throws 2006 at us. To prevent crazy recursive calls, sleep here. ACE_OS::sleep(3); // Sleep 3 seconds return _HandleMySQLErrno(lErrno); // Call self (recursive) } case ER_LOCK_DEADLOCK: return false; // Implemented in TransactionTask::Execute and DatabaseWorkerPool<T>::DirectCommitTransaction // Query related errors - skip query case ER_WRONG_VALUE_COUNT: case ER_DUP_ENTRY: return false; // Outdated table or database structure - terminate core case ER_BAD_FIELD_ERROR: case ER_NO_SUCH_TABLE: sLog->outError(LOG_FILTER_SQL, "Your database structure is not up to date. Please make sure you've executed all queries in the sql/updates folders."); ACE_OS::sleep(10); std::abort(); return false; case ER_PARSE_ERROR: sLog->outError(LOG_FILTER_SQL, "Error while parsing SQL. Core fix required."); ACE_OS::sleep(10); std::abort(); return false; default: sLog->outError(LOG_FILTER_SQL, "Unhandled MySQL errno %u. Unexpected behaviour possible.", errNo); return false; } }
bool MySqlConnection::Execute(PreparedStmt* stmt) { if (!m_Mysql) return false; uint32 index = stmt->m_stmtIndex; MySqlPreparedStmt* pStmt = GetPreparedStatement(index); pStmt->m_pPrepareStmt = stmt; stmt->m_pStmt = pStmt; stmt->bindParameters(); MYSQL_STMT* pMySqlStmt = pStmt->GetMySqlStmt(); MYSQL_BIND* pMySqlBind = pStmt->GetBind(); if (mysql_stmt_bind_param(pMySqlStmt, pMySqlBind)) { uint32 lErrno = mysql_errno(m_Mysql); ERROR_LOG("MySqlConnection::execute mysql_stmt_bind_param failed %u\n", lErrno); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) return Execute(stmt); // Try again pStmt->clearParameters(); return false; } TRACE_LOG("Exe SQL(p): %s\n\n", pStmt->getQueryString(m_queries[index].first).c_str()); if (mysql_stmt_execute(pMySqlStmt)) { uint32 lErrno = mysql_errno(m_Mysql); ERROR_LOG("MySqlConnection::execute mysql_stmt_bind_param failed %u\n", lErrno); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) return Execute(stmt); // Try again pStmt->clearParameters(); return false; } return true; }
bool MySQLConnection::_HandleMySQLErrno(uint32 errNo) { switch (errNo) { case 2006: // "MySQL server has gone away" case 2013: // "Lost connection to MySQL server during query" case 2048: // "Invalid connection handle" case 2055: // "Lost connection to MySQL server at '%s', system error: %d" { m_reconnecting = true; uint64 oldThreadId = mysql_thread_id(GetHandle()); mysql_close(GetHandle()); if (this->Open()) // Don't remove 'this' pointer unless you want to skip loading all prepared statements.... { sLog->outSQLDriver("Connection to the MySQL server is active."); if (oldThreadId != mysql_thread_id(GetHandle())) sLog->outSQLDriver("Successfully reconnected to %s @%s:%s (%s).", m_connectionInfo.database.c_str(), m_connectionInfo.host.c_str(), m_connectionInfo.port_or_socket.c_str(), (m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous"); m_reconnecting = false; return true; } uint32 lErrno = mysql_errno(GetHandle()); // It's possible this attempted reconnect throws 2006 at us. To prevent crazy recursive calls, sleep here. ACE_OS::sleep(3); // Sleep 3 seconds return _HandleMySQLErrno(lErrno); // Call self (recursive) } case 1213: // "Deadlock found when trying to get lock; try restarting transaction" return false; // Implemented in TransactionTask::Execute and DatabaseWorkerPool<T>::DirectCommitTransaction // Query related errors - skip query case 1058: // "Column count doesn't match value count" case 1062: // "Duplicate entry '%s' for key '%d'" return false; // Outdated table or database structure - terminate core case 1054: // "Unknown column '%s' in '%s'" case 1146: // "Table '%s' doesn't exist" WPFatal(!errNo, "Your database structure is not up to date. Please make sure you've executed all queries in the sql/updates folders."); return false; default: sLog->outSQLDriver("Unhandled MySQL errno %u. Unexpected behaviour possible.", errNo); return false; } }
bool MySqlConnection::Execute(const char* sql) { if (!m_Mysql) return false; if (mysql_query(m_Mysql, sql)) { uint32 lErrno = mysql_errno(m_Mysql); ERROR_LOG("execute sql:%s failed return [%u] %s\n", sql, lErrno, mysql_error(m_Mysql)); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) return Execute(sql); // Try again return false; } return true; }
bool MySQLConnection::_Query(const char *sql, MYSQL_RES **pResult, MYSQL_FIELD **pFields, uint64* pRowCount, uint32* pFieldCount) { if (!m_Mysql) return false; { uint32 _s = 0; if (sLog->GetSQLDriverQueryLogging()) _s = getMSTime(); if (mysql_query(m_Mysql, sql)) { uint32 lErrno = mysql_errno(m_Mysql); sLog->outSQLDriver("SQL: %s", sql); sLog->outSQLDriver("ERROR: [%u] %s", lErrno, mysql_error(m_Mysql)); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) return _Query(sql, pResult, pFields, pRowCount, pFieldCount); // We try again return false; } else if (sLog->GetSQLDriverQueryLogging()) { sLog->outSQLDriver("[%u ms] SQL: %s", getMSTimeDiff(_s,getMSTime()), sql); } *pResult = mysql_store_result(m_Mysql); *pRowCount = mysql_affected_rows(m_Mysql); *pFieldCount = mysql_field_count(m_Mysql); } if (!*pResult ) return false; if (!*pRowCount) { mysql_free_result(*pResult); return false; } *pFields = mysql_fetch_fields(*pResult); return true; }
bool MySQLConnection::_Query(const char *sql, MYSQL_RES **pResult, MYSQL_FIELD **pFields, uint64* pRowCount, uint32* pFieldCount) { if (!m_Mysql) return false; { uint32 _s = getMSTime(); if (mysql_query(m_Mysql, sql)) { uint32 lErrno = mysql_errno(m_Mysql); sLog->outInfo(LOG_FILTER_SQL, "SQL: %s", sql); sLog->outError(LOG_FILTER_SQL, "[%u] %s", lErrno, mysql_error(m_Mysql)); if (lErrno == ER_BAD_FIELD_ERROR || lErrno == ER_NO_SUCH_TABLE || lErrno == ER_PARSE_ERROR) sLog->outError(LOG_FILTER_SQL, "TrinityCore TRANSFERT ERROR %u : query : %s", lErrno, sql); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) return _Query(sql, pResult, pFields, pRowCount, pFieldCount); // We try again return false; } else sLog->outDebug(LOG_FILTER_SQL, "[%u ms] SQL: %s", getMSTimeDiff(_s, getMSTime()), sql); *pResult = mysql_store_result(m_Mysql); *pRowCount = mysql_affected_rows(m_Mysql); *pFieldCount = mysql_field_count(m_Mysql); } if (!*pResult ) return false; if (!*pRowCount) { mysql_free_result(*pResult); return false; } *pFields = mysql_fetch_fields(*pResult); return true; }
bool MySQLConnection::_HandleMySQLErrno(uint32 errNo) { switch (errNo) { case 2006: // "MySQL server has gone away" case 2013: // "Lost connection to MySQL server during query" case 2048: // "Invalid connection handle" case 2055: // "Lost connection to MySQL server at '%s', system error: %d" { m_reconnecting = true; uint64 oldThreadId = mysql_thread_id(GetHandle()); mysql_close(GetHandle()); if (this->Open()) // Don't remove 'this' pointer unless you want to skip loading all prepared statements.... { sLog->outSQLDriver("Die Verbindung zum MySQL-Server aktiv ist."); if (oldThreadId != mysql_thread_id(GetHandle())) sLog->outSQLDriver("Online %s @%s:%s (%s).", m_connectionInfo.database.c_str(), m_connectionInfo.host.c_str(), m_connectionInfo.port_or_socket.c_str(), (m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous"); m_reconnecting = false; return true; } uint32 lErrno = mysql_errno(GetHandle()); // It's possible this attempted reconnect throws 2006 at us. To prevent crazy recursive calls, sleep here. ACE_OS::sleep(3); // Sleep 3 seconds return _HandleMySQLErrno(lErrno); // Call self (recursive) } case 1213: // "Deadlock found when trying to get lock; try restarting transaction" return false; // Implemented in TransactionTask::Execute and DatabaseWorkerPool<T>::DirectCommitTransaction // Query related errors - skip query case 1058: // "Column count doesn't match value count" case 1062: // "Duplicate entry '%s' for key '%d'" case 1054: // "Unknown column '%s' in 'order clause'" return false; default: sLog->outSQLDriver("Unbehandelte MySQL Err %u. Unerwarteter Fehler.", errNo); return false; } }
bool MySQLConnection::_HandleMySQLErrno(uint32 errNo) { sLog->outDebug("%s", __FUNCTION__); switch (errNo) { case 2006: // "MySQL server has gone away" case 2013: // "Lost connection to MySQL server during query" case 2048: // "Invalid connection handle" case 2055: // "Lost connection to MySQL server at '%s', system error: %d" { m_reconnecting = true; uint64 oldThreadId = mysql_thread_id(GetHandle()); mysql_close(GetHandle()); if (this->Open()) // Don't remove 'this' pointer unless you want to skip loading all prepared statements.... { sLog->outSQLDriver("Connection to the MySQL server is active."); if (oldThreadId != mysql_thread_id(GetHandle())) sLog->outSQLDriver("Succesfuly reconnected to %s @%s:%s (%s).", m_connectionInfo.database.c_str(), m_connectionInfo.host.c_str(), m_connectionInfo.port_or_socket.c_str(), (m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous"); m_reconnecting = false; return true; } uint32 lErrno = mysql_errno(GetHandle()); // It's possible this attempted reconnect throws 2006 at us. To prevent crazy recursive calls, sleep here. ACE_OS::sleep(3); // Sleep 3 seconds return _HandleMySQLErrno(lErrno); // Call self (recursive) } // Query related errors - skip query case 1058: // "Column count doesn't match value count" case 1062: // "Duplicate entry '%s' for key '%d'" case 1054: // "Unknown column '%s' in 'order clause'" return false; default: sLog->outSQLDriver("Unhandled MySQL errno %u. Unexpected behaviour possible.", errNo); return false; } }
bool MySQLConnection::_Query(const char *sql, MYSQL_RES **pResult, MYSQL_FIELD **pFields, uint64* pRowCount, uint32* pFieldCount) { if (!m_Mysql) return false; { boost::timer _s; if (mysql_query(m_Mysql, sql)) { uint32 lErrno = mysql_errno(m_Mysql); _LOG_INFO(LOG_FILTER_SQL, "SQL: %s", sql); _LOG_ERROR(LOG_FILTER_SQL, "[%u] %s", lErrno, mysql_error(m_Mysql)); if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) return _Query(sql, pResult, pFields, pRowCount, pFieldCount); // We try again return false; } else _LOG_DEBUG(LOG_FILTER_SQL, "[%u ms] SQL: %s",(uint32)_s.elapsed(), sql); *pResult = mysql_store_result(m_Mysql); *pRowCount = mysql_affected_rows(m_Mysql); *pFieldCount = mysql_field_count(m_Mysql); } if (!*pResult ) return false; if (!*pRowCount) { mysql_free_result(*pResult); return false; } *pFields = mysql_fetch_fields(*pResult); return true; }
bool MySQLConnection::_HandleMySQLErrno(uint32 errNo, uint8 attempts /*= 5*/) { switch (errNo) { case CR_SERVER_GONE_ERROR: case CR_SERVER_LOST: #ifdef CR_INVALID_CONN_HANDLE case CR_INVALID_CONN_HANDLE: #endif case CR_SERVER_LOST_EXTENDED: { if (m_Mysql) { TC_LOG_ERROR("sql.sql", "Lost the connection to the MySQL server!"); mysql_close(GetHandle()); m_Mysql = nullptr; } /*no break*/ } case CR_CONN_HOST_ERROR: { TC_LOG_INFO("sql.sql", "Attempting to reconnect to the MySQL server..."); m_reconnecting = true; uint32 const lErrno = Open(); if (!lErrno) { // Don't remove 'this' pointer unless you want to skip loading all prepared statements... if (!this->PrepareStatements()) { TC_LOG_FATAL("sql.sql", "Could not re-prepare statements!"); std::this_thread::sleep_for(std::chrono::seconds(10)); std::abort(); } TC_LOG_INFO("sql.sql", "Successfully reconnected to %s @%s:%s (%s).", m_connectionInfo.database.c_str(), m_connectionInfo.host.c_str(), m_connectionInfo.port_or_socket.c_str(), (m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous"); m_reconnecting = false; return true; } if ((--attempts) == 0) { // Shut down the server when the mysql server isn't // reachable for some time TC_LOG_FATAL("sql.sql", "Failed to reconnect to the MySQL server, " "terminating the server to prevent data corruption!"); // We could also initiate a shutdown through using std::raise(SIGTERM) std::this_thread::sleep_for(std::chrono::seconds(10)); std::abort(); } else { // It's possible this attempted reconnect throws 2006 at us. // To prevent crazy recursive calls, sleep here. std::this_thread::sleep_for(std::chrono::seconds(3)); // Sleep 3 seconds return _HandleMySQLErrno(lErrno, attempts); // Call self (recursive) } } case ER_LOCK_DEADLOCK: return false; // Implemented in TransactionTask::Execute and DatabaseWorkerPool<T>::DirectCommitTransaction // Query related errors - skip query case ER_WRONG_VALUE_COUNT: case ER_DUP_ENTRY: return false; // Outdated table or database structure - terminate core case ER_BAD_FIELD_ERROR: case ER_NO_SUCH_TABLE: TC_LOG_ERROR("sql.sql", "Your database structure is not up to date. Please make sure you've executed all queries in the sql/updates folders."); std::this_thread::sleep_for(std::chrono::seconds(10)); std::abort(); return false; case ER_PARSE_ERROR: TC_LOG_ERROR("sql.sql", "Error while parsing SQL. Core fix required."); std::this_thread::sleep_for(std::chrono::seconds(10)); std::abort(); return false; default: TC_LOG_ERROR("sql.sql", "Unhandled MySQL errno %u. Unexpected behaviour possible.", errNo); return false; } }
bool MySqlConnection::_HandleMySQLErrno(uint32 errNo) { switch (errNo) { case CR_SERVER_GONE_ERROR: case CR_SERVER_LOST: case CR_INVALID_CONN_HANDLE: case CR_SERVER_LOST_EXTENDED: { m_reconnecting = true; mysql_close(GetHandle()); if (this->Open()) { m_reconnecting = false; DEBUG_LOG("mysql connect reconnect success\n"); return true; } uint32 lErrno = mysql_errno(GetHandle()); // It's possible this attempted reconnect throws 2006 at us. To prevent crazy recursive calls, sleep here. ::sleep(3); // Sleep 3 seconds return _HandleMySQLErrno(lErrno); // Call self (recursive) } break; case ER_LOCK_DEADLOCK: { return false; // Implemented in TransactionTask::Execute and DatabaseWorkerPool<T>::DirectCommitTransaction } break; // Query related errors - skip query case ER_WRONG_VALUE_COUNT: case ER_DUP_ENTRY: { return false; } break; // Outdated table or database structure - terminate core case ER_BAD_FIELD_ERROR: case ER_NO_SUCH_TABLE: { ERROR_LOG("Your database structure is not up to date. Please make sure you've executed all queries in the sql/updates folders.\n"); ::sleep(10); std::abort(); return false; } break; case ER_PARSE_ERROR: { ERROR_LOG("Error while parsing SQL. Core fix required.\n"); ::sleep(10); std::abort(); return false; } break; default: { ERROR_LOG("Unhandled MySQL errno %u. Unexpected behaviour possible.\n", errNo); return false; } break; } return false; }