diff --git a/SaneEconomyCore/src/main/java/org/appledash/saneeconomy/economy/backend/type/EconomyStorageBackendMySQL.java b/SaneEconomyCore/src/main/java/org/appledash/saneeconomy/economy/backend/type/EconomyStorageBackendMySQL.java index 12f160a..886cc93 100644 --- a/SaneEconomyCore/src/main/java/org/appledash/saneeconomy/economy/backend/type/EconomyStorageBackendMySQL.java +++ b/SaneEconomyCore/src/main/java/org/appledash/saneeconomy/economy/backend/type/EconomyStorageBackendMySQL.java @@ -128,10 +128,12 @@ public class EconomyStorageBackendMySQL extends EconomyStorageBackendCaching { dbConn.executeAsyncOperation((conn) -> { try { ensureAccountExists(economable, conn); + conn.prepareStatement("LOCK TABLE " + dbConn.getTable("saneeconomy_balances") + " WRITE").execute(); PreparedStatement statement = dbConn.prepareStatement(conn, String.format("UPDATE `%s` SET balance = ? WHERE `unique_identifier` = ?", dbConn.getTable("saneeconomy_balances"))); statement.setDouble(1, newBalance); statement.setString(2, economable.getUniqueIdentifier()); statement.executeUpdate(); + conn.prepareStatement("UNLOCK TABLES").execute(); } catch (Exception e) { balances.put(economable.getUniqueIdentifier(), oldBalance); throw new RuntimeException("SQL error has occurred.", e); diff --git a/SaneEconomyCore/src/main/java/org/appledash/saneeconomy/utils/database/MySQLConnection.java b/SaneEconomyCore/src/main/java/org/appledash/saneeconomy/utils/database/MySQLConnection.java index 8292aa7..7cdb7f9 100644 --- a/SaneEconomyCore/src/main/java/org/appledash/saneeconomy/utils/database/MySQLConnection.java +++ b/SaneEconomyCore/src/main/java/org/appledash/saneeconomy/utils/database/MySQLConnection.java @@ -66,24 +66,26 @@ public class MySQLConnection { }); } - // This is a big weird because it has to account for recursion... + // This is a bit weird because it has to account for recursion... private void doExecuteAsyncOperation(int levels, Consumer callback) { - if (levels == 1) { + if (levels == 1) { // First level waitForSlot(); openTransactions.incrementAndGet(); } + try (Connection conn = openConnection()) { callback.accept(conn); } catch (Exception e) { if (levels > dbCredentials.getMaxRetries()) { throw new RuntimeException("This shouldn't happen (database error)", e); } + LOGGER.severe("An internal SQL error has occured, trying up to " + (5 - levels) + " more times..."); e.printStackTrace(); levels++; doExecuteAsyncOperation(levels, callback); } finally { - if (levels == 1) { + if (levels == 1) { // The recursion is done, we may have thrown an exception, maybe not - but either way we need to mark the transaction as closed. openTransactions.decrementAndGet(); } }