在多线程环境中使用select for update nowait时,只读结果集的操作无效

时间:2015-05-29 14:12:59

标签: java multithreading jdbc oracle11g

对于Oracle数据库,以下程序仅针对某些线程抛出SQL异常。为什么要从CONCUR_UPDATABLE to CONCUR_READ_ONLY降级resultSetConcurrency?在单线程环境中,这种情况不会发生。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


public class Main extends Thread {

    public static final String DBURL = "jdbc:oracle:thin:@localhost:1521:DB";
    public static final String DBUSER = "USER";
    public static final String DBPASS = "PASS";

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        for(int i=0; i<20; i++)
            new Main().start();
    }

    @Override
    public void run() {

        try
        {
            DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());

            Connection con = DriverManager.getConnection(DBURL, DBUSER, DBPASS);
            con.setAutoCommit(false);

            try(PreparedStatement pstmt = con.prepareStatement("SELECT COLUMN1 FROM TABLE1 FOR UPDATE NOWAIT", 
                    ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE))
            {               
                ResultSet rs = pstmt.executeQuery();

                if (rs.next()) {
                    rs.updateString(1, "12345");
                    rs.updateRow();
                }            
            }
            finally
            {
                con.commit();
                con.close();
            }
        }
        catch(SQLException e)
        {
            if(!e.toString().contains("NOWAIT"))
                e.printStackTrace();
        }
    }

}

1 个答案:

答案 0 :(得分:0)

您可以查看针对结果集/语句/连接引发的警告,以查看降级的原因。在ls -R | grep '.*[.]fvp' 调用后添加此内容:

executeQuery()

在这种情况下,您有时会看到:

  

警告:99999:17091
  警告:无法以请求的类型和/或并发级别创建结果集:ORA-00054:资源繁忙并且在指定NOWAIT或超时已到期时获取

您正在寻找NOWAIT例外,但您会收到警告。我不清楚为什么你仍然在那个场景中得到一个结果集;但是如果你看到它,你至少可以捕获该警告,而不是进入结果集循环。