【发布时间】:2015-02-06 12:58:50
【问题描述】:
我正在尝试使用简单的 JDBC 应用程序从 linux 服务器(比如服务器 X)进行批量插入。
当我尝试批量大小为 5 的应用程序时,它运行良好。
但是当我尝试批量大小为 500 时,它挂起。我没有收到任何错误或异常。当我查询数据库时,我可以看到插入了 500 行,但 java 应用程序只是挂起。 java 应用程序没有退出。
应用程序只是在以下方法调用处挂起
try{
// register driver
// establish connection
// create statement
// add insert commands from inputFile to the batch
statemnt.executeBatch(); //---------------application hangs here
}
//catch block followed by finally block to close resources
我在不同的linux服务器上尝试了相同的应用程序,我能够成功执行批量大小为500的应用程序,应用程序运行良好并正常退出。
应用程序仅在服务器 X 中挂起,并且仅在批处理大小较大时才挂起。
然后我检查了服务器X中挂起的进程的strace,发现它在以下系统调用中循环
$ strace -f -p [hung-java-process-id]
[pid 104273] futex(0x7ffe78013728, FUTEX_WAKE_PRIVATE, 1) = 0
[pid 104273] clock_gettime(CLOCK_MONOTONIC, {9635863, 882169546}) = 0
[pid 104273] clock_gettime(CLOCK_MONOTONIC, {9635863, 882258933}) = 0
[pid 104273] clock_gettime(CLOCK_REALTIME, {1417787058, 859159155}) = 0
[pid 104273] futex(0x7ffe78013754, FUTEX_WAIT_PRIVATE, 1, {0, 49972845}) = -1 ETIMEDOUT (Connection timed out)
[pid 104273] futex(0x7ffe78013728, FUTEX_WAKE_PRIVATE, 1) = 0
[pid 104273] clock_gettime(CLOCK_MONOTONIC, {9635863, 932601035}) = 0
[pid 104273] clock_gettime(CLOCK_MONOTONIC, {9635863, 932677888}) = 0
[pid 104273] clock_gettime(CLOCK_REALTIME, {1417787058, 909571241}) = 0
[pid 104273] futex(0x7ffe78013754, FUTEX_WAIT_PRIVATE, 1, {0, 49977759}) = -1 ETIMEDOUT (Connection timed out)
[pid 104273] futex(0x7ffe78013728, FUTEX_WAKE_PRIVATE, 1) = 0
我检查了挂起的java进程打开的打开文件列表,得到以下输出,显示db连接仍然打开。
$ lsof -p [hung-java-process-id] | grep TCP
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 104273 userid 14u IPv6 1674188639 0t0 TCP serverX:55744->dbServer:blackjack (ESTABLISHED)
我还尝试将连接 AutoCommit 属性设置为 false,然后在 executeBatch 方法之后调用 commit。但我仍然面临同样的问题。
我还尝试将批次拆分为较小的批次。该应用程序在批量大小为 29 时运行良好,但是当我将批量大小增加到 30 时,它只是挂起,没有任何错误或异常。
我找不到问题的原因。 如果 strace 显示问题的原因,那么请告诉我,它到底是什么意思以及如何解决它? 任何帮助都会非常有用。提前致谢。
请注意我使用的是 Java 7。
我想这个问题可能是由 linux 机器(服务器 X)中的某些配置引起的,因为相同的应用程序在其他机器上运行良好,以实现大批量。任何与机器配置相关的见解都会对我非常有用。
【问题讨论】:
-
不知道是连接被劫持还是因为运行时间长而被强制关闭?您的连接池超时设置是否相同?是否有某种可以终止连接的数据库服务器代理?
-
您可能需要指定 jdbc 客户端和服务器、jvm 版本。很难弄清楚它为什么挂起/等待资源。
-
java 应用程序本身的堆栈跟踪是什么?
-
Linux 服务器是 Red Hat,Java 版本 7,Database Teradata 14.10
-
@jtahlborn 我没有收到任何异常,但应用程序挂起。我正在从 main 方法调用 executeBatch 方法。
标签: java linux unix jdbc bulkinsert