多个Java线程在并发运行时访问同一个DB记录

多个Java线程在并发运行时访问同一个DB记录,java,mysql,multithreading,Java,Mysql,Multithreading,我这里有一个相当简单的Java类,它创建了两个线程池 连接到正在运行的URL流并逐行读取条目,并将每个条目提交到后端MySQL数据库中 产生多个线程,每个线程将执行相同的进程(如下所示) 1.从上面获取最早的数据库条目 2.对其进行相应的解析和处理 3.将多个部分保存到另一个DB表 4.从运行表中删除此DB条目,表示其分析已完成 5.端螺纹 我需要2个池的原因是,读取过程比分析快得多,如果我读取并分析每个条目,因为它通过条目返回太快,传入流中断。通过这种分离,读取可以按照需要的速度进行,

我这里有一个相当简单的Java类,它创建了两个线程池

  • 连接到正在运行的URL流并逐行读取条目,并将每个条目提交到后端MySQL数据库中

  • 产生多个线程,每个线程将执行相同的进程(如下所示)

1.从上面获取最早的数据库条目

2.对其进行相应的解析和处理

3.将多个部分保存到另一个DB表

4.从运行表中删除此DB条目,表示其分析已完成

5.端螺纹

我需要2个池的原因是,读取过程比分析快得多,如果我读取并分析每个条目,因为它通过条目返回太快,传入流中断。通过这种分离,读取可以按照需要的速度进行,分析可以按照需要的速度进行,因为它知道要跟踪的记录是安全的,并且可以跟踪

我遇到的问题是,每个并发线程都得到相同的最早记录。我需要知道最好的方法是什么,以确保单独的线程都同时运行,但每个线程都访问唯一的数据库条目

提前谢谢

编辑=================================

感谢大家迄今为止的回复

为了进一步扩展我在这里尝试的当前设置,也许这个代码段会有帮助

try
    {
        String strQuery1 = "SELECT lineID,line FROM lineProcessing ORDER BY lineID ASC LIMIT 1;";
        String strQuery2 = "DELETE from lineProcessing WHERE lineID = ?";

        DBConnector dbc = new DBConnector(driver,url,userName,passwd); 
        Connection con = dbc.getConnection();
        con.setAutoCommit(false);
        PreparedStatement pstmt = con.prepareStatement(strQuery1);
        rs = pstmt.executeQuery();
        
        //Now extract the line & Id from the returned result set
        while (rs.next()) {
            lineID = Integer.parseInt(rs.getString(1));
            line = rs.getString(2);
        } //end while 
        
        //Now delete that entry so that it cannot be analysed again...
        pstmt = con.prepareStatement(strQuery2);
        pstmt.setString(1, lineID.toString());
        int res=pstmt.executeUpdate();
        
        con.commit();
        con.setAutoCommit(true);
        con.close();
    }
    catch (SQLException e) {
        System.out.println(">>>EXCEPTION FOUND IN QUERY = " + strQuery1 + " __or__ " + strQuery2);
        e.printStackTrace();
    }
…如您所见,基本上打开一个DB连接,将其设置为“Autocommit=false”,执行QUERY1,执行QUERY2,提交两个事务,最后关闭连接。这应该是每个单独线程需要完成的全部任务。问题是,我在分析线程池中运行的每个X线程都会生成,并且都会同时执行这批代码(这是我所期望的),但不尊重我认为我在上面设置的对DB的单连接访问。然后它们都返回同一行进行分析。当线程下一次循环迭代#2时,它们都会返回上一次删除后的最后一行进行分析

请提供进一步的建议-包括一个通过java强制事务SQL的好例子


再次感谢各位。

首先,添加一个可为空的datetime列,表示该行已在某个特定时间“拾取”

然后在处理线程中:

  • 启动交易
  • 查找“拾取”时间为null的最早行
  • 将拾取时间更新为当前系统时间
  • 提交事务 确保您的设置为至少
    读取未提交的
    ,并且两个线程不应获得同一行。此外,如果一个处理线程死亡并放弃了它的行,您可以通过定期查询“拾取”时间早于某个值的行来发现这一点,并通过将拾取时间设置为null来重新处理这些行


    或者直接切换到事务性消息队列,它会自动完成大部分任务。

    首先,添加一个可为空的datetime列,表示该行已在某个特定时间“提取”

    然后在处理线程中:

  • 启动交易
  • 查找“拾取”时间为null的最早行
  • 将拾取时间更新为当前系统时间
  • 提交事务 确保您的设置为至少
    读取未提交的
    ,并且两个线程不应获得同一行。此外,如果一个处理线程死亡并放弃了它的行,您可以通过定期查询“拾取”时间早于某个值的行来发现这一点,并通过将拾取时间设置为null来重新处理这些行


    或者直接切换到事务性消息队列,它会自动完成大部分任务。

    另一种解决方案是让所有工作线程都在包含行键的单例上等待。写入行,将键放入对象中,然后通知。“下一个”工作线程将拾取密钥并对其进行操作。您需要确保工作线程正在等待,而不是等待。

    另一种解决方案是让所有工作线程在包含行键的单例上等待。写入行,将键放入对象中,然后通知。“下一个”工作线程将拾取密钥并对其进行操作。您需要确保工作人员正在等待,而不是等待。

    也许您需要将逻辑从“获取最旧的db条目”更改为“获取尚未处理的最旧db条目”?也许您需要将逻辑从“获取最旧的db条目”更改为“获取尚未处理的最旧db条目”?谢谢Chris…我已经编辑了上面的原始问题,请看一看,如果您能提供进一步帮助,请告诉我。干杯。你在这里的评论意味着你没有阅读(或没有试图实现)我的答案。试着去实现它。更新:我实现了一个与您的建议类似的工作版本,方法是在数据库中调用一个存储过程,其中包含封装在事务/提交结构中的两个SQL查询。这成功地使每个线程能够唯一地调用该过程,并防止每个线程检索相同的DB记录,因为每个线程的访问、读取和删除都是通过单个事务进行的。再次感谢。谢谢克里斯……我已经编辑了上面的原始问题,请看一看,如果你能进一步帮助我,请告诉我。干杯。你在这里的评论意味着你没有阅读(或没有试图实现)我的答案。试着去实现它。更新:我实现了一个与您的建议类似的工作版本,方法是在数据库中调用一个存储过程,该存储过程包含封装在事务/提交str中的两个SQL查询