Experimental: Lock MySQL tables so as not to break things?!

This commit is contained in:
AppleDash 2017-06-10 16:32:37 -04:00
parent dc6909af0f
commit da16d4474e
2 changed files with 7 additions and 3 deletions

View File

@ -128,10 +128,12 @@ public class EconomyStorageBackendMySQL extends EconomyStorageBackendCaching {
dbConn.executeAsyncOperation((conn) -> { dbConn.executeAsyncOperation((conn) -> {
try { try {
ensureAccountExists(economable, conn); 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"))); PreparedStatement statement = dbConn.prepareStatement(conn, String.format("UPDATE `%s` SET balance = ? WHERE `unique_identifier` = ?", dbConn.getTable("saneeconomy_balances")));
statement.setDouble(1, newBalance); statement.setDouble(1, newBalance);
statement.setString(2, economable.getUniqueIdentifier()); statement.setString(2, economable.getUniqueIdentifier());
statement.executeUpdate(); statement.executeUpdate();
conn.prepareStatement("UNLOCK TABLES").execute();
} catch (Exception e) { } catch (Exception e) {
balances.put(economable.getUniqueIdentifier(), oldBalance); balances.put(economable.getUniqueIdentifier(), oldBalance);
throw new RuntimeException("SQL error has occurred.", e); throw new RuntimeException("SQL error has occurred.", e);

View File

@ -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<Connection> callback) { private void doExecuteAsyncOperation(int levels, Consumer<Connection> callback) {
if (levels == 1) { if (levels == 1) { // First level
waitForSlot(); waitForSlot();
openTransactions.incrementAndGet(); openTransactions.incrementAndGet();
} }
try (Connection conn = openConnection()) { try (Connection conn = openConnection()) {
callback.accept(conn); callback.accept(conn);
} catch (Exception e) { } catch (Exception e) {
if (levels > dbCredentials.getMaxRetries()) { if (levels > dbCredentials.getMaxRetries()) {
throw new RuntimeException("This shouldn't happen (database error)", e); 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..."); LOGGER.severe("An internal SQL error has occured, trying up to " + (5 - levels) + " more times...");
e.printStackTrace(); e.printStackTrace();
levels++; levels++;
doExecuteAsyncOperation(levels, callback); doExecuteAsyncOperation(levels, callback);
} finally { } 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(); openTransactions.decrementAndGet();
} }
} }