Skip to content

Commit ec2d459

Browse files
committed
Add more protections against MariaDB 1020
Affects issues: - #4468
1 parent 89528aa commit ec2d459

4 files changed

Lines changed: 61 additions & 4 deletions

File tree

Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerTableResultTransaction.java

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ public StorePlayerTableResultTransaction(ProviderInformation information, Parame
6767
this(information.getPluginName(), parameters.getServerUUID(), information.getName(), parameters.getPlayerUUID(), value);
6868
}
6969

70+
@Override
71+
protected IsolationLevel getDesiredIsolationLevel() {
72+
return IsolationLevel.READ_COMMITTED;
73+
}
74+
7075
@Override
7176
protected void performOperations() {
7277
execute(storeValue());
@@ -80,26 +85,45 @@ private Executable storeValue() {
8085
}
8186

8287
Integer tableID = query(tableID());
88+
query(lockRows(tableID));
8389

8490
List<Object[]> rows = table.getRows();
8591
Integer oldRowCount = query(currentRowCount(tableID));
8692
int newRowCount = rows.size();
8793

8894
if (oldRowCount < newRowCount) {
89-
updateRows(tableID, oldRowCount, rows);
9095
insertNewRows(tableID, oldRowCount, rows);
96+
updateRows(tableID, oldRowCount, rows);
9197
} else if (oldRowCount == newRowCount) {
9298
// No need to delete or insert rows
9399
updateRows(tableID, oldRowCount, rows);
94100
} else {
95101
// oldRowCount > newRowCount
96-
updateRows(tableID, newRowCount, rows);
97102
deleteOldRows(tableID, newRowCount);
103+
updateRows(tableID, newRowCount, rows);
98104
}
99105
return false;
100106
};
101107
}
102108

109+
private Query<Object> lockRows(Integer tableID) {
110+
String sql = SELECT + "*" + FROM + TABLE_NAME +
111+
WHERE + TABLE_ID + "=?" +
112+
AND + USER_UUID + "=?" + lockForUpdate();
113+
return new QueryStatement<>(sql) {
114+
@Override
115+
public void prepare(PreparedStatement statement) throws SQLException {
116+
statement.setInt(1, tableID);
117+
statement.setString(2, playerUUID.toString());
118+
}
119+
120+
@Override
121+
public Object processResults(ResultSet set) {
122+
return null;
123+
}
124+
};
125+
}
126+
103127
private void deleteOldRows(Integer tableID, int afterRow) {
104128
String sql = DELETE_FROM + TABLE_NAME +
105129
WHERE + TABLE_ID + "=?" +

Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerTableResultTransaction.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ protected void performOperations() {
6969
execute(storeValue());
7070
}
7171

72+
@Override
73+
protected IsolationLevel getDesiredIsolationLevel() {
74+
return IsolationLevel.READ_COMMITTED;
75+
}
76+
7277
private Executable storeValue() {
7378
return connection -> {
7479
int maxColumnSize = table.getMaxColumnSize();
@@ -83,15 +88,15 @@ private Executable storeValue() {
8388
int newRowCount = rows.size();
8489

8590
if (oldRowCount < newRowCount) {
86-
updateRows(tableID, oldRowCount, rows);
8791
insertNewRows(tableID, oldRowCount, rows);
92+
updateRows(tableID, oldRowCount, rows);
8893
} else if (oldRowCount == newRowCount) {
8994
// No need to delete or insert rows
9095
updateRows(tableID, oldRowCount, rows);
9196
} else {
9297
// oldRowCount > newRowCount
93-
updateRows(tableID, newRowCount, rows);
9498
deleteOldRows(tableID, newRowCount);
99+
updateRows(tableID, newRowCount, rows);
95100
}
96101
return false;
97102
};

Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/Transaction.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,23 @@ private void initializeConnection(SQLDB db) {
183183
}
184184

185185
private void initializeTransaction() {
186+
setIsolationLevel();
186187
try {
187188
createSavePoint();
188189
} catch (SQLException e) {
189190
throw new DBOpException(getClass().getSimpleName() + " save point initialization failed: " + e.getMessage(), e);
190191
}
191192
}
192193

194+
private void setIsolationLevel() {
195+
if (dbType == DBType.MYSQL && attempts == 1) {
196+
IsolationLevel desiredIsolationLevel = getDesiredIsolationLevel();
197+
if (desiredIsolationLevel != IsolationLevel.UNCHANGED) {
198+
execute("SET TRANSACTION ISOLATION LEVEL " + desiredIsolationLevel.name().replace('_', ' '));
199+
}
200+
}
201+
}
202+
193203
private void createSavePoint() throws SQLException {
194204
try {
195205
this.savepoint = connection.setSavepoint();
@@ -298,4 +308,13 @@ protected boolean hasTable(String tableName) {
298308
}
299309

300310
protected String lockForUpdate() {return db.getSql().lockForUpdate();}
311+
312+
protected IsolationLevel getDesiredIsolationLevel() {
313+
return IsolationLevel.UNCHANGED;
314+
}
315+
316+
public enum IsolationLevel {
317+
UNCHANGED,
318+
READ_COMMITTED
319+
}
301320
}

Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/init/CreateIndexTransaction.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import com.djrapitops.plan.storage.database.DBType;
2020
import com.djrapitops.plan.storage.database.queries.schema.MySQLSchemaQueries;
2121
import com.djrapitops.plan.storage.database.sql.tables.*;
22+
import com.djrapitops.plan.storage.database.sql.tables.extension.ExtensionPlayerTableValueTable;
23+
import com.djrapitops.plan.storage.database.sql.tables.extension.ExtensionServerTableValueTable;
2224
import com.djrapitops.plan.storage.database.transactions.Transaction;
2325
import org.apache.commons.text.TextStringBuilder;
2426

@@ -66,6 +68,13 @@ protected void performOperations() {
6668

6769
createIndex(SessionsTable.TABLE_NAME, "plan_session_join_address_index",
6870
SessionsTable.JOIN_ADDRESS_ID);
71+
72+
createIndex(ExtensionPlayerTableValueTable.TABLE_NAME, "plan_extension_player_table_value_player_index",
73+
ExtensionPlayerTableValueTable.TABLE_ID,
74+
ExtensionPlayerTableValueTable.USER_UUID);
75+
createIndex(ExtensionServerTableValueTable.TABLE_NAME, "plan_extension_server_table_value_server_index",
76+
ExtensionServerTableValueTable.TABLE_ID,
77+
ExtensionServerTableValueTable.SERVER_UUID);
6978
}
7079

7180
private void createIndex(String tableName, String indexName, String... indexedColumns) {

0 commit comments

Comments
 (0)