fix(Core/Shared/DB): recommit transactions on dead-lock error (#6069)

This commit is contained in:
UltraNix
2021-06-01 15:36:59 +02:00
committed by GitHub
parent 1889fffbde
commit beb4df9d3e
4 changed files with 20 additions and 12 deletions
@@ -7,6 +7,8 @@
#include "DatabaseWorkerPool.h" #include "DatabaseWorkerPool.h"
#include "DatabaseEnv.h" #include "DatabaseEnv.h"
#include <mysqld_error.h>
#define MIN_MYSQL_SERVER_VERSION 50700u #define MIN_MYSQL_SERVER_VERSION 50700u
#define MIN_MYSQL_CLIENT_VERSION 50700u #define MIN_MYSQL_CLIENT_VERSION 50700u
@@ -318,7 +320,8 @@ template <class T>
void DatabaseWorkerPool<T>::DirectCommitTransaction(SQLTransaction& transaction) void DatabaseWorkerPool<T>::DirectCommitTransaction(SQLTransaction& transaction)
{ {
T* con = GetFreeConnection(); T* con = GetFreeConnection();
if (con->ExecuteTransaction(transaction)) int errorCode = con->ExecuteTransaction(transaction);
if (!errorCode)
{ {
con->Unlock(); // OK, operation succesful con->Unlock(); // OK, operation succesful
return; return;
@@ -326,12 +329,12 @@ void DatabaseWorkerPool<T>::DirectCommitTransaction(SQLTransaction& transaction)
//! Handle MySQL Errno 1213 without extending deadlock to the core itself //! Handle MySQL Errno 1213 without extending deadlock to the core itself
//! TODO: More elegant way //! TODO: More elegant way
if (con->GetLastError() == 1213) if (errorCode == ER_LOCK_DEADLOCK)
{ {
uint8 loopBreaker = 5; uint8 loopBreaker = 5;
for (uint8 i = 0; i < loopBreaker; ++i) for (uint8 i = 0; i < loopBreaker; ++i)
{ {
if (con->ExecuteTransaction(transaction)) if (!con->ExecuteTransaction(transaction))
break; break;
} }
} }
@@ -355,11 +355,11 @@ void MySQLConnection::CommitTransaction()
Execute("COMMIT"); Execute("COMMIT");
} }
bool MySQLConnection::ExecuteTransaction(SQLTransaction& transaction) int MySQLConnection::ExecuteTransaction(SQLTransaction& transaction)
{ {
std::list<SQLElementData> const& queries = transaction->m_queries; std::list<SQLElementData> const& queries = transaction->m_queries;
if (queries.empty()) if (queries.empty())
return false; return -1;
BeginTransaction(); BeginTransaction();
@@ -376,8 +376,9 @@ bool MySQLConnection::ExecuteTransaction(SQLTransaction& transaction)
if (!Execute(stmt)) if (!Execute(stmt))
{ {
LOG_INFO("sql.driver", "[Warning] Transaction aborted. %u queries not executed.", (uint32)queries.size()); LOG_INFO("sql.driver", "[Warning] Transaction aborted. %u queries not executed.", (uint32)queries.size());
int errorCode = GetLastError();
RollbackTransaction(); RollbackTransaction();
return false; return errorCode;
} }
} }
break; break;
@@ -388,8 +389,9 @@ bool MySQLConnection::ExecuteTransaction(SQLTransaction& transaction)
if (!Execute(sql)) if (!Execute(sql))
{ {
LOG_INFO("sql.driver", "[Warning] Transaction aborted. %u queries not executed.", (uint32)queries.size()); LOG_INFO("sql.driver", "[Warning] Transaction aborted. %u queries not executed.", (uint32)queries.size());
int errorCode = GetLastError();
RollbackTransaction(); RollbackTransaction();
return false; return errorCode;
} }
} }
break; break;
@@ -402,7 +404,7 @@ bool MySQLConnection::ExecuteTransaction(SQLTransaction& transaction)
// and not while iterating over every element. // and not while iterating over every element.
CommitTransaction(); CommitTransaction();
return true; return 0;
} }
MySQLPreparedStatement* MySQLConnection::GetPreparedStatement(uint32 index) MySQLPreparedStatement* MySQLConnection::GetPreparedStatement(uint32 index)
@@ -78,7 +78,7 @@ public:
void BeginTransaction(); void BeginTransaction();
void RollbackTransaction(); void RollbackTransaction();
void CommitTransaction(); void CommitTransaction();
bool ExecuteTransaction(SQLTransaction& transaction); int ExecuteTransaction(SQLTransaction& transaction);
operator bool () const { return m_Mysql != nullptr; } operator bool () const { return m_Mysql != nullptr; }
void Ping() { mysql_ping(m_Mysql); } void Ping() { mysql_ping(m_Mysql); }
+6 -3
View File
@@ -7,6 +7,8 @@
#include "DatabaseEnv.h" #include "DatabaseEnv.h"
#include "Transaction.h" #include "Transaction.h"
#include <mysqld_error.h>
//- Append a raw ad-hoc query to the transaction //- Append a raw ad-hoc query to the transaction
void Transaction::Append(const char* sql) void Transaction::Append(const char* sql)
{ {
@@ -63,14 +65,15 @@ void Transaction::Cleanup()
bool TransactionTask::Execute() bool TransactionTask::Execute()
{ {
if (m_conn->ExecuteTransaction(m_trans)) int errorCode = m_conn->ExecuteTransaction(m_trans);
if (!errorCode)
return true; return true;
if (m_conn->GetLastError() == 1213) if (errorCode == ER_LOCK_DEADLOCK)
{ {
uint8 loopBreaker = 5; // Handle MySQL Errno 1213 without extending deadlock to the core itself uint8 loopBreaker = 5; // Handle MySQL Errno 1213 without extending deadlock to the core itself
for (uint8 i = 0; i < loopBreaker; ++i) for (uint8 i = 0; i < loopBreaker; ++i)
if (m_conn->ExecuteTransaction(m_trans)) if (!m_conn->ExecuteTransaction(m_trans))
return true; return true;
} }