MySQL-JDBC-同时选择和删除

时间:2018-08-08 15:04:11

标签: java mysql jdbc

因此,我的客户端程序运行此代码以获取行数据并在之后将其删除。事情是在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");

2 个答案:

答案 0 :(得分:1)

如果您希望您的SELECT阻止该行上的后续读取,直到您删除它,那么就如Mark在其注释中所指出的那样,您需要

  • 启用交易(setAutoCommit(false)
  • 将事务隔离设置为SERIALIZABLE,并且
  • 使用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;