如何通过 JDBC 取消长时间运行的 MySQL 查询?

问题描述 投票:0回答:1

我有一个长时间运行的查询,通过 JDBC 对 MySQL 8 数据库运行。我的目标是能够在某些触发器(例如外部信号、数据处理错误等)上退出此查询并取消查询。根据我在 MySQL 论坛上的测试和研究,

statement.cancel()
实际上没有做任何事情。

我怎样才能实现这个目标?除了在单独的连接上调用

KILL <pid>
之外,没有其他方法吗?如果是这样,我可以管理它,但我不明白如何识别长时间运行的查询的确切 PID。有没有可靠的方法?

简而言之,如何使用 MySQL Connector J 按需取消长时间运行的查询?如果可能的话,我真的很感激包含代码的工作示例的链接。

作为参考,这里是一些用 Kotlin 编写的示例代码:

val data = produce<List<Data>> {
    db.connection.use { conn ->
        conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY).use { stmt ->
            stmt.fetchSize = Int.MIN_VALUE
            stmt.executeQuery("...").use { rs ->
                var batch = mutableListOf<Data>()
                while (rs.next()) {
                    // Handle result set here
                    val data = Data(
                        id = rs.getLong("id"),
                        subAccountId = rs.getInt("sub_account_id")
                    )
                    batch.add(data)
                    if (batch.size >= 100) {
                        println("Sending batch...")
                        send(batch)
                        if (done) {
                            println("Done, closing...")
                            close()
                            break
                        }
                        batch = mutableListOf()
                    }
                }
                println("Out of loop, cancelling statement")
                synchronized(this) { // my lame attempt at cancelling
                    println("In synchronized")
                    if (!stmt.isClosed) {
                        println("Statement is not yet closed") // DOES print
                        stmt.cancel()
                        stmt.close()
                        conn.close() // probably pointless but I tried
                    }
                }
            }
            println("Out of statement") // does NOT print
        }
        println("Out of connection") // does NOT print
    }
    println("End of production...") // does NOT print
}

我可以在控制台中看到“语句尚未关闭”,但除此之外什么也没有。

java mysql kotlin jdbc
1个回答
0
投票

如果你想杀死它,你应该使用单独的线程。

ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> future = executor.submit(() -> {
    /////////// 1st thread //////////
    Statement stmt = connection.createStatement();
    ResultSet rs = stmt.executeQuery("SELECT ...");
});

///////////// 2nd thread //////////
future.cancel(true);
© www.soinside.com 2019 - 2024. All rights reserved.