【发布时间】:2025-11-25 14:05:01
【问题描述】:
我在使用 MySQL 的 SELECT .. FOR UPDATE 时遇到问题,这是我要运行的查询:
SELECT * FROM tableName WHERE HostName='UnknownHost'
ORDER BY UpdateTimestamp asc limit 1 FOR UPDATE
在此之后,相关线程将执行更新并更改主机名,然后它应该解锁该行。
我正在运行一个多线程的 java 应用程序,所以 3 个线程正在运行这个 SQL 语句,但是当线程 1 运行它时,它不会锁定线程 2 和 3 的结果。因此线程 2 和 3 正在获取相同的结果,他们可以更新同一行。
每个线程都在自己的mysql连接上。
我正在使用 Innodb,事务隔离 = READ-COMMITTED,并且在执行 select for update 之前自动提交已关闭
我可以错过什么吗?或者也许有更好的解决方案? 非常感谢。
代码:
public BasicJDBCDemo()
{
Le_Thread newThread1=new Le_Thread();
Le_Thread newThread2=new Le_Thread();
newThread1.start();
newThread2.start();
}
线程:
class Le_Thread extends Thread
{
public void run()
{
tring name = Thread.currentThread().getName();
System.out.println( name+": Debut.");
long oid=Util.doSelectLockTest(name);
Util.doUpdateTest(oid,name);
}
}
选择:
public static long doSelectLockTest(String threadName)
{
System.out.println("[OUTPUT FROM SELECT Lock ]...threadName="+threadName);
PreparedStatement pst = null;
ResultSet rs=null;
Connection conn=null;
long oid=0;
try
{
String query = "SELECT * FROM table WHERE Host=?
ORDER BY Timestamp asc limit 1 FOR UPDATE";
conn=getNewConnection();
pst = conn.prepareStatement(query);
pst.setString(1, DbProperties.UnknownHost);
System.out.println("pst="+threadName+"__"+pst);
rs = pst.executeQuery();
if (rs.first())
{
String s = rs.getString("HostName");
oid = rs.getLong("OID");
System.out.println("oid_oldest/host/threadName=="+oid+"/"+s+"/"+threadName);
}
}
catch (SQLException ex)
{
ex.printStackTrace();
}
finally
{
DBUtil.close(pst);
DBUtil.close(rs);
DBUtil.close(conn);
}
return oid;
}
请帮忙....:
结果:
线程 1:首次亮相。 线程 2:首次亮相。 [选择锁的输出]...threadName=Thread-1 新连接.. [选择锁的输出]...threadName=Thread-2 新连接.. pst=Thread-2: SELECT * FROM b2biCheckPoint WHERE HostName='UnknownHost' ORDER BY UpdateTimestamp asc limit 1 FOR UPDATE pst=Thread-1: SELECT * FROM b2biCheckPoint WHERE HostName='UnknownHost' ORDER BY UpdateTimestamp asc limit 1 FOR UPDATE oid_oldest/host/threadName==1/UnknownHost/Thread-2 oid_oldest/host/threadName==1/UnknownHost/Thread-1 [执行更新] ... oid = 1, thread=Thread-2 新连接.. [执行更新] ... oid = 1, thread=Thread-1 pst_threadname=Thread-2: UPDATE b2bicheckpoint SET HostName='1_host_Thread-2',UpdateTimestamp=1294940161838 where OID = 1 新连接.. pst_threadname=Thread-1: UPDATE b2bicheckpoint SET HostName='1_host_Thread-1',UpdateTimestamp=1294940161853 where OID = 1【问题讨论】:
-
你是如何明智地实现这段代码的?