因此,我的客户端程序运行此代码以获取行数据并在之后将其删除。事情是在SELECT和DELETE之间存在60-130毫秒的延迟,在那个时候另一个客户端可以抓住同一行。有什么办法可以同时进行SELECT和DELETE来阻止这种冲突的发生?
String filterQuery = "SELECT token_id FROM table WHERE expires <= ? LIMIT 1;";
PreparedStatement preparedStmt = conn.prepareStatement(filterQuery);
preparedStmt.setLong(1, System.currentTimeMillis());
long startTime = System.currentTimeMillis();
ResultSet result = preparedStmt.executeQuery();
String token_id = null;
while (result.next()) {
System.out.println(result.getString(1));
token_id = result.getString(1);
}
filterQuery = "DELETE FROM table WHERE token_id = ?;";
preparedStmt = conn.prepareStatement(filterQuery);
preparedStmt.setString(1, token_id);
preparedStmt.execute();
System.out.println(System.currentTimeMillis() - startTime+" milliseconds");
答案 0 :(得分:1)
如果您希望您的SELECT阻止该行上的后续读取,直到您删除它,那么就如Mark在其注释中所指出的那样,您需要
setAutoCommit(false)
)SELECT ... FOR UPDATE
此示例代码对我有用:
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
conn.setAutoCommit(false);
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT token_id FROM tokens ORDER BY token_id LIMIT 1 FOR UPDATE");
rs.next();
int token_id = rs.getInt("token_id");
System.out.printf("Got %d.%n", token_id);
PreparedStatement ps = conn.prepareStatement("DELETE FROM tokens WHERE token_id=?");
ps.setInt(1, token_id);
ps.executeUpdate();
conn.commit();
答案 1 :(得分:0)
由于我误解了XD问题,因此编辑了整个答案
看看mySQL REPEATABLE READ,您的SQ代码将类似于此
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
SELECT token_id FROM table WHERE expires <= 'Example';
DELETE FROM table WHERE token_id = 'ExampleID!';
COMMIT;