【问题标题】:Stuck thread in update statement: cancelling or closing the statement, and interrupt the thread does not work更新语句卡住线程:取消或关闭语句,中断线程不起作用
【发布时间】:2023-04-03 12:36:01
【问题描述】:

我已经阅读了很多关于停止线程的信息,但我无法找到解决问题的方法:

我有一个连接了 3 个线程的 Sybase DB 连接。 加上一个线程来监控这 3 个线程。

但是,由于服务器超载(我知道:我应该解决这个问题,但我们还没有钱),调用: Statement stmt.executeUpdate("从 some_table 更新一些东西"); 永远不会回来。

这是线程的大致作用(不可编译,因为无论如何它都不可重现):

class runQuery implements Runnable {
    public Connection conn;
    public long lastQueryRunTime = 0;
    public Statement stmt;
    public volatile keepongoing = true;

    runQuery(Connection conn, String Probe, String Server, int thisthread) {
         this.conn = conn;
         Class.forName("com.sybase.jdbc2.jdbc.SybDriver");
         conn = DriverManager.getConnection("jdbc:sybase:Tds:"+Server+":4100?SERVICENAME="+Probe,"login","password");
    }

    public void run () {
        while(keepongoing) {
        query = "update something from some_table";
        lastQueryRunTime = System.currentTimeMillis()/1000;
        stmt = conn.createStatement();
        stmt.setQueryTimeout(4);
        int result = stmt.executeUpdate(query);
        lastQueryRunTime = 0;
    }
}

这应该给出一个粗略的想法。 另一方面,我有一个“MonitorThemAll”线程来检查 lastQueryRunTime:如果它太长,我想......做点什么!

所以,从监控线程中,我尝试了: 更改 keepongoing 标志...但由于线程卡在更新查询中,它并没有做太多 然后: stmt.cancel(), stmt.close() => 似乎没什么用。执行 kill -3 表明线程仍然停留在 executeUpdate 行。

我转向更有力的解决方案: conn.close() => 从那里,我每次尝试 stmt.cancel/close 时都会收到异常“JZ0C0:连接已关闭”(这些异常是由 stmt.cancel/close 命令引发的:即:它们在MonitorThemAll 线程,不在 runQuery 线程中......) 并且: mythread.interrupt() => 之后仍然停留在更新查询中!

我在这里和谷歌上找到的解决方案已经用完了... 由于 thread.close() 已被弃用(尽管如此,我想避免,以便我可以恢复使用的资源),我不知道我还能尝试什么......

有人知道要尝试的事情吗?

【问题讨论】:

  • 更新后不想执行conn.commit()吗?我认为您有经典的数据库死锁问题。
  • 如果线程继续运行(即多个更新仍在进行),或者它只是卡在 executeUpdate 中,您是否尝试过打印?
  • 你能澄清你想要做什么吗?如果数据库需要很长时间才能响应......你想......什么?
  • executeUpdate 实际上永远不会返回...“正常”超时由“stmt.setQueryTimeout(4);”正确处理(在 4 秒后超时,在这种情况下我会捕获异常,并在存储桶中重新添加查询)
  • 关于提交:它是一个 Sybase/Netcool DB,所以不需要提交。

标签: java multithreading


【解决方案1】:

假设您的问题是 sql 查询太长而无法执行,您可以将 sql 查询传递给后台线程来执行查询并在查询完成时获取结果(通过回调侦听器或队列)。

【讨论】:

  • 实际上,查询永远不会返回......它只是永远卡在那里。 “正常超时”已由“stmt.setQueryTimeout(4);”处理抛出异常,我处理
  • 另外,我想要实现的,最后:线程卡在 executeUpdate "forever" => 我需要一种方法来退出这个 executeUpdate 并继续前进(这是最优雅的方法,但是通常的取消/关闭不起作用)...或以某种方式使线程停止,或杀死线程或任何需要的东西(从优雅的退出到残暴的杀死)
  • 你不能在Java中杀死一个线程。只有尝试中断它,如果行为正常它就会停止。所以你需要调查为什么查询永远不会返回并解决这个问题。首先要解决的问题请注意,表已被锁定,这就是查询不返回的原因。尝试验证这一点
  • 好吧,我试过打断它,但它什么也没做(语句可能没有实现interruptibleChannel),是的:我知道问题来自数据库:它只在服务器运行时出现方式方式超载。此外,当表被锁定时,“stmt.setQueryTimeout(4);”触发器,我已经正确处理了。问题来自一个线程由于某种原因被锁定的事实,我需要找到一种方法来解锁它,在 Java 端
  • 你是说stmt.setQueryTimeout虽然表被锁定,但你得到异常并且线程继续?如果是这样,那你为什么说查询永远不会返回?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-29
  • 2012-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多