我有这种情况,我需要从mysql中选择一批数据,然后相应地更新它们。
这就是我在伪代码方面做的事情:
//select
results --> select row1 from mytable where x=0;
//update
update --> update mytable set x=1 where row1 in (results of previous query)
这是与之相关的代码:
Set<String> output= select_row1(nextPatch); // select_row1 returns a list of string where x=0
String blockQuery= "update mytable set x=1 where row1 in (" + ouput.toString + ");" //output toString method is triggered to work accordingly.
update(blockQuery); //this method will set column x=1 so it won't be used by other threads.
作为我的计划的一部分,我需要使用返回的output
。所以必须有2个查询。
如果我只使用一台机器,这种机制很有效,但它在并发系统中失败了。 我想要做的是确保不再选择所选的行(通过设置x = 1),但是当运行的线程太多时。他们仍然可以选择相同的结果。
任何想法如何解决?
答案 0 :(得分:2)
编辑
尝试锁定正在使用的表格(请在此处阅读Table-Locking Restrictions and Conditions)。警告这可能会导致线程抛出Exceptions
,如果它们无法访问表,那么您可能需要在线程中捕获并处理它们。
LOCK TABLES mytable WRITE, mytable READ;
update mytable set x=1 where row1 in (select row1 from mytable where x=0);
UNLOCK TABLES;
你能不做这样的事吗?
update mytable set x=1 where row1 in (select row1 from mytable where x=0)
答案 1 :(得分:0)
右, 首先感谢@MihaiC缩小搜索范围以找到解决方案。 我终于设法找到了这样做的方法。如果有人提出同样的问题,这是一个简短的说明。
所以问题是我想选择一组行,然后相应地为并发系统更新它们。
如果您只有一个线程,则使用两个单独的查询(如所示)将起作用。但是如果许多线程试图选择和更新,则会失败,因为他们会在第一个线程更新之前选择相同的行。"For UPDATE"
selectquery
醇>
查询是:
query = "SELECT row1 FROM mytable WHERE x=0 LIMIT 10;"
*更改为:*
query ="SELECT row1,x FROM mytable WHERE x=0 LIMIT 10 FOR UPDATE;"
Statement
,而是使用PreparedStatement
:<强> 是: 强>
Statement stmt = conn.createStatement();
stmt.execute(selectQuery);
ResultSet r= stmt.getResultSet();
更改为:
PreparedStatement stmt =conn.prepareStatement(query, ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE);
stmt.execute(query);
ResultSet r= stmt.getResultSet();
<强> 是: 强>
while(r.next()){
String row1=r.getString("row1");
}
更改为:
while(r.next()){
String row1=r.getString("row1");
r.updateString("x", "1");
}
这将确保每个线程将选择一组行并相应地更新它们,而不会相互干扰。
同样This post非常有用: