【问题标题】:SELECT FOR UPDATE not working with JDBC and OracleSELECT FOR UPDATE 不适用于 JDBC 和 Oracle
【发布时间】:2011-10-20 10:53:57
【问题描述】:

我编写了一个简单的 Java 程序,它打开一个事务,选择一些记录,执行一些逻辑,然后更新它们。我希望记录被锁定,所以我使用了 SELECT...FOR UPDATE。

该程序在 MS SQL Server 2005 上运行良好,但在 Oracle 10g 中记录没有锁定!

知道为什么吗?

我按如下方式创建连接:

Connection connection = DriverManager.getConnection(URL, User, Password);
connection.setAutoCommit(false);

如果我从 Oracle SQL Developer 客户端执行 SELECT..FOR UPDATE,我可以看到记录被锁定,所以我认为这可能是 JDBC 驱动程序问题而不是数据库问题,但我不能在网上找不到任何有用的东西。

这些是我正在使用的 JDBC 驱动程序的详细信息:

Manifest-Version: 1.0
Implementation-Vendor:  Oracle Corporation
Implementation-Title:   ojdbc14.jar
Implementation-Version: Oracle JDBC Driver version - "10.2.0.2.0"
Implementation-Time:    Tue Jan 24 08:55:21 2006
Specification-Vendor:   Oracle Corporation
Sealed: true
Created-By: 1.4.2_08 (Sun Microsystems Inc.)
Specification-Title:    Oracle JDBC driver classes for use with JDK14
Specification-Version:  Oracle JDBC Driver version - "10.2.0.2.0"

【问题讨论】:

  • 请更具体地说明您遇到的问题:什么不起作用?
  • SELECT...FOR UPDATE 不会锁定记录。如果我尝试从另一个程序同时更新相同的记录,则更新成功,而我的理解是这些记录应该被锁定,直到我提交或回滚事务(这实际上是 SQL Server 发生的情况)。

标签: oracle select jdbc locking


【解决方案1】:

抱歉,我无法重现此行为。您究竟是如何在 JDBC 中运行 SELECT ... FOR UPDATE 查询的?

我有一个表,locktest,其中包含以下数据:

SQL> 从 locktest 中选择 *; 甲乙 ---------- ---------- 1 0 2 0 3 0 4 0 5 0

我也有这个 Java 类:

import oracle.jdbc.OracleDriver;
import java.sql.*;

public class LockTest {

    public static void main(String[] args) throws Exception {
        DriverManager.registerDriver(new OracleDriver());
        Connection c  = DriverManager.getConnection(
            "jdbc:oracle:thin:@localhost:1521:XE", "user", "password");

        c.setAutoCommit(false);
        Statement stmt = c.createStatement(
            ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);

        ResultSet rSet = stmt.executeQuery(
            "SELECT a, b FROM locktest FOR UPDATE");

        while (rSet.next()) {
            if (rSet.getInt(1) <= 3) {
                rSet.updateInt(2, 1);
            }
        }

        System.out.println("Sleeping...");
        Thread.sleep(Long.MAX_VALUE);
    }
}

当我运行这个 Java 类时,它会对表进行一些更新,然后开始休眠。它休眠以保持事务打开并因此保留锁。

C:\Users\Luke\stuff>java LockTest 睡眠...

当它处于休眠状态时,我尝试同时更新 SQL*Plus 中的表:

SQL> update locktest set b = 1 where a

此时,SQL*Plus 挂起,直到我终止 Java 程序。

【讨论】:

  • 我还需要把 rSet.updateRow();在 updateInt 之后让 udpate 工作。
  • 我修改了上面的代码,选择了一个 TYPE_FORWARD_ONLY、CONCUR_READ_ONLY 结果集,但查询仍然锁定了其他客户端,无法在同一行上执行 SELECT ... FOR UPDATE。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-05
  • 1970-01-01
  • 2011-06-08
  • 1970-01-01
  • 2016-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多