关于jdbc并发问题: 有二个客户端使用人员(用A,B来区分人员)。先后更新oracle库上的某一条数据。因为一些偶然的原因造成A 第一次更新数据的行为一直属于未提交状态。然后 B 再进行更新这条数据操作的时候,于是就造成死锁状态。B不知道是什么原因,于是他多次进行更新数据操作,于是造成大面积死锁现象。 其中我使用了struts的令牌防止刷新页面而造成的重复提交操作。但对于目前这种现象没有任何防治效果。我对jdbc进行了多次断点测试操作。发现是在执行 
objStatement = objConnection.prepareStatement(execsql,java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,java.sql.ResultSet.CONCUR_READ_ONLY);
objStatement.execute();//是在执行这一处代码的时候,就卡主了,不往下面走。
这样就造成了objStatement.close();关闭不了,Connection 也无法commit。然后
finally{}//代码块中关闭连接操作无法完成,链接池中的链接也无法释放。
从而导致了连接池中有效链接全部都非法占用。造成程序速度非常慢。
由于我是用使用jdbc访问数据库层得。暂时没有太好用的思路。跪求高手
给个思路,给个建议。万分感激。分会持续散给大家。求求大家帮帮忙。

解决方案 »

  1.   

    不知道我理解你的意思对不对
    如果原因是:第一次更新数据的行为一直属于未提交状态的话
    我建议你加强connection的控制
    使用proxy+threadlocal,这样,在proxy关闭,这样应该不会出现共用一个连接而造成死锁
      

  2.   

    哈,给位大大谅解谅解。是在是家里有事情急着处理。怠慢了。在此向给位路过的大大致歉!第一次更新数据的行为,是大批量的更新数据,这个过程一般都会是在10分钟到30分钟之间。
    而且更新批量数据是放在一个大事务中然后才一起提交的。我应该这样说明:二套程序使用的是同一个数据库。所有A用程序批量更新账户的余额。
    而B是客户,他这个时候去消费。于是就出现我上面所说的情况了。
    A用的程序是pb写的。而B用的程序是用java写的。 A程序无法进行优化修改。
    所以我想使用jdbc 在更新数据的时候 ,如果当前数据正在处于更新状态当中,就报一个错误提示。我当时想hibernate可能对这一种情况进行了异常处理。所以写了个例子进行测试。
    发现一个很有趣的现象。我分别使用了sybase库,和oracle 分别进行测试。sybase库报出了update 异常。 而oracle 则任何异常都没有提示。
    我是这样测试的:先把这条记录锁住,不提交。这样就模拟出一直未提交的情况。 sybase提示错误,而oracle就没一点错误信息提示。
    另外关于 longintstring 大哥 说 的proxy+threadlocal 方法。希望longintstring  能深入一点。
    我也会在继续百度和 google。再次谢谢大家的鼎力支持,我这二天会一刻也不离电脑盘。等待拜读各位神仙的思路。
    谢谢!
      

  3.   

    java.util.concurrent  我查了一些资料,发现 jdk1.5版本后提供了 这个并发库。发觉里面看起来还是有很好用的api,用来处理阻塞队列,和设置超时。 目前正在写例子测试中,还不知道能不能满足我想要的结果。如果各位路过的神仙曾经有使用过这个库的经验。希望赐教,给个看法,或者一些例子什么的。给小弟一个启发。知道分少了很多。但是还是会多赚点分,继续散给大家。
    另外,如果我把Connection的事务提到 TRANSACTION_REPEATABLE_READ 隔离级别,但是写了例子。也没有作用。代码如下:import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    public class Ping{
       public static void runJdbc() {
            String url="jdbc:oracle:thin:@127.0.0.1:1521:cftest";
            String user="anning";
            String password="cfsi_any_user08";
    Connection objConnection = null;
        try {
    Class.forName("oracle.jdbc.driver.OracleDriver");
    System.out.println("chuangjian");
    PreparedStatement objStatement = null;
    objConnection = DriverManager.getConnection(url, user,password);
    objConnection.setTransactionIsolation(objConnection.TRANSACTION_SERIALIZABLE);
    String sql="UPDATE KC04 SET AKC085=? WHERE AAC001=? ";
    objStatement=objConnection.prepareStatement(sql);
    objStatement.setString(1, "11");
    objStatement.setString(2, "1504011003658200000");
    System.out.println("chuangjian0");
    objStatement.execute();
    System.out.println("chuangjian1");
    objStatement.close();
    objConnection.commit();
    System.out.println("chuangjian2");
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    } catch (SQLException e) {
    e.printStackTrace();
    } finally {
         try {
    objConnection.close();
    } catch (SQLException e) {
    }
    }
    }
        public static void main(String[] args)
        {
         runJdbc();
        }
    }
      

  4.   

    我在cmd 下 用 plsql 命令连上oracle 库,然后写一个update语句,执行这条记录之后没有commit;然后,我再执行上面的代码,发现到objStatement.execute(); 就卡主,没有往下走。我就像达到 如果在 runJdbc方法内 执行的时间超过我设定的限制时间,那么就回滚数据并执行关闭数据库连接。 我使用了 java.util.concurrent 包下的 ScheduledExecutorService接口先:final ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
              Runnable pinger = new Runnable() {
                public void run() {
                  System.out.println("PING!");//回滚数据,释放池连接
                    ses.shutdown();
                }
            };
    ses.schedule(pinger, 5, TimeUnit.SECONDS);//5 秒之后开始执行一次。
    .... 一些执行sql语句代码。
    ses.shutdown();
    但是效果也不行。
      

  5.   

    Statement, PreparedStatement 有个 setQueryTimeout 方法可以设置超时时间。最主要的是,你那个事务要挂起二三十分钟,这势必得锁住啊!
      

  6.   

    是啊,但是那一块的业务的处理,暂时目前无法处理优化。。所以 就只能通过这个笨办法去 实现。其实,我最希望的是,有一个异常机制最好了。 向sybase库,如果sybase库要更新的这条记录,是锁住状态,那么,hibernate的异常机制,直接就报一个 update 失败的异常。这样通过框架 就能控制异常了。  而现在 oracle 居然没一点反应,很费解
      

  7.   

    衷心谢谢 ()火龙果()  大大 给出的建议。我试了。效果挺好的。比我自己这二天研究使用 jdk并发库所使用的例子强多了。  衷心感谢你 以及 各位路过的神仙大大。 小弟在此拜谢。