java – JDBC使用SELECT FOR UPDATE锁定一行,不起作用
发布时间:2020-12-14 05:50:05 所属栏目:Java 来源:网络整理
导读:我遇到 MySQL的SELECT问题.. FOR UPDATE,这是我试图运行的查询: SELECT * FROM tableName WHERE HostName='UnknownHost' ORDER BY UpdateTimestamp asc limit 1 FOR UPDATE 在此之后,相关的线程将执行UPDATE并更改HostName,然后它应该解锁该行. 我正在运行
我遇到
MySQL的SELECT问题.. FOR UPDATE,这是我试图运行的查询:
SELECT * FROM tableName WHERE HostName='UnknownHost' ORDER BY UpdateTimestamp asc limit 1 FOR UPDATE 在此之后,相关的线程将执行UPDATE并更改HostName,然后它应该解锁该行. 我正在运行一个多线程的java应用程序,所以3个线程正在运行这个SQL语句,但是当线程1运行它时,它不会将其结果从线程2&因此,线程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; } 请帮忙…. : 结果: Thread-1: Debut. Thread-2: Debut. [OUTPUT FROM SELECT Lock ]...threadName=Thread-1 New connection.. [OUTPUT FROM SELECT Lock ]...threadName=Thread-2 New connection.. 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 [Performing UPDATE] ... oid = 1,thread=Thread-2 New connection.. [Performing UPDATE] ... oid = 1,thread=Thread-1 pst_threadname=Thread-2: UPDATE b2bicheckpoint SET HostName='1_host_Thread-2',UpdateTimestamp=1294940161838 where OID = 1 New connection.. pst_threadname=Thread-1: UPDATE b2bicheckpoint SET HostName='1_host_Thread-1',UpdateTimestamp=1294940161853 where OID = 1 解决方法
你非常困惑,但至少在编辑后事情看起来更好.有多种方法可以做到这一点,但我发现最好的方法是实际使用JDBC的ResultSet.update *方法:
首先,您需要使用ResultSet.CONCUR_UPDATABLE参数准备SELECT … FOR UPDATE语句,如下所示: ps = conn.prepareStatement(query,ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE); 然后,您必须使用ResultSet实际更新表: if(rs.next()) { rs.updateString(columnIndex,"new_hostname"); rs.updateRow(); } 第三,您可能需要使用我可以在更新中看到的事务.希望你的DbUtil.close方法不会抛出任何异常,检查null等等.另外,如果你的方法变得更复杂,你也应该有回滚逻辑. 你不应该因为任何原因修改my.ini. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- java中BigDecimal进行加减乘除的基本用法
- Struts2基本配置文件
- java – warning:类型'[io.realm.OrderListRealmProxy
- 如何帮助java tomcat进程重新获得已用内存?
- java – 在Apache Web Server中评估的表达式语言
- java – 如何为ScrollView设置OnClickListener?
- SpringMVC+ZTree实现树形菜单权限配置的方法
- java – @ManyToOne映射不适用于连接继承
- 哪个手机支持哪个J2ME(Java Micro Edition)规格?
- 在Java中放置comprobations的位置?