gpt4 book ai didi

java - 如何中止 JDBC Postgresql CopyManager 复制?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:51:05 24 4
gpt4 key购买 nike

有没有办法取消通过调用 copyIn() 启动的复制过程?单独线程中的方法?

比如说,我有一个 csv 文件列表,我需要从中复制,以最大限度地利用数据库服务器的能力。因此,我为 n 个文件创建了 n 个线程连接,但我找不到一种方法来中止单个操作,例如,如果选择了错误的文件。

杀死线程不起作用 - COPY 只是继续运行。

FutureTask<>类用于创建线程,因此有一个线程列表 - 每个 csv 一个。

调用 task.cancel(true)在服务器上的复制过程方面没有任何作用。只有System.exit()可以用火杀死它。

有什么想法吗?

我的一些代码:

Uploader.java implements Callable

public static long uploadFile(final File file, final String tableName) {

long status = 0;
try {
CopyManager copyManager =
new CopyManager((BaseConnection) new DataSource().connect());
FileReader reader = new FileReader(file);
status = copyManager.copyIn(sql, reader);
} catch (SQLException | IOException e) {
...
}
return status;
}

@Override
public Long call() throws Exception {
return uploadFile(file, tableName);
}

Upload files method body

for (File file : files) {
FutureTask<Long> ftask =
new FutureTask<>(
new Uploader(defaultTableName, file)
);
tasks.add(ftask);
execService.execute(ftask);
}

已解决:

已找到解决方案,但需要对代码进行一些更改。

Upload files method body现在看起来像这样

for (File file : files) {
Uploader uploader = new Uploader(defaultTableName, file);
uploaders.add(uploader);
Future<Long> f = execService.submit(uploader);

//save the Future to get the copy result when finished

}

有了这个,我们可以很容易地调用一些Uploader的方法,可以关闭数据库连接并正确处理异常。它将停止在服务器上复制。

我承认该解决方案可能不是最优雅的解决方案,但它确实有效,运行速度很快,而且不需要太多代码。

最佳答案

PostgreSQL 实际上并不支持带内查询取消。

当您从 JDBC 驱动程序请求取消查询时,它会创建一个新连接来发送取消消息。 (这意味着如果您处于 max_connections,取消将失败,这有点反常)。

这样做的结果是您可以自己做同样的事情:

  • 在开始复制操作之前使用pg_backend_pid()获取worker的进程ID;

  • 当您想要取消副本时,打开一个新连接并使用之前记录的 pid 发出 pg_cancel_backend(?)。如果它没有停止,您可以稍等片刻,然后执行 pg_terminate_backend(?)

这些是普通的 SQL 级函数。

唯一真正的问题是取消和终止请求是 session 级别而不是语句级别。所以他们可以在语句完成和新语句开始时进行比赛,例如:

  • client1:COPY 开始
  • client2:连接发送取消消息
  • client1:复制完成
  • client1:新的独立副本开始
  • client2 发送 pg_cancel_backend(...)

此时,第二个副本会被终止,这可能不是你想要的。因此,您必须确保使用适当的排除客户端来防止这种情况发生,确保在开始新语句之前完成所有未完成的取消请求。

无论如何,IIRC JDBC 驱动程序在内部也有同样的问题。这是团队真正想要一种方法来取消特定的唯一每 session 语句序列号的原因之一,例如(当前不存在的)pg_cancel_backend(pid, statementnumber) 如果出现错误则中止该语句已经终止,而不是发送取消。

关于java - 如何中止 JDBC Postgresql CopyManager 复制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18608144/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com