gpt4 book ai didi

java - Jaybird SocketInputStream.socketread0 线程阻塞

转载 作者:行者123 更新时间:2023-11-30 05:24:48 27 4
gpt4 key购买 nike

我正在使用 JDBC 连接到 firebird。

<groupId>org.firebirdsql.jdbc</groupId>
<artifactId>jaybird-jdk18</artifactId>
<version>3.0.5</version>

当我读取数据时:

resultSet.next(); //resultSet is instance of FBResultSet

有时线程会在这里阻塞:

 private native int socketRead0(FileDescriptor fd,
byte b[], int off, int len,
int timeout)
throws IOException;

并且该线程将永远不会继续。我需要重新启动整个应用程序。 :(

如何解决这个问题?我从这里尝试了一些参数: https://dzone.com/articles/threads-stuck-in-javanetsocketinputstreamsocketrea

-Dsun.net.client.defaultConnectTimeout=10000
-Dsun.net.client.defaultReadTimeout=10000

但没有积极的结果。我什至不知道超时值是多少。我无法在那个地方调试它。 (java.net.SocketInputStream)

数据库的连接是连接到云服务器的,我认为这就是问题所在。

是否有可能以某种方式解决这个问题?或者给firebird jdbc设置超时?

感谢您的回答。

编辑:这是卡线的屏幕: enter image description here

最佳答案

您的情况的根本原因是当在 firebird.conf 中启用线路加密(设置 WireCrypt =启用)。

我之前只在Jaybird 4按特定顺序进行测试时才遇到过这个问题,而且由于该版本尚未发布,所以我没有优先考虑找到根本原因。

在您的帮助下(再次感谢!)我能够找出问题所在。此错误现已在 Jaybird 3.0.8 中修复,可从 Firebird: JDBC Driver 获取。 .

错误说明

Firebird 有线协议(protocol)中某些类型的缓冲区(例如列数据)用字节填充到四的倍数。 Jaybird 中的实现依靠 InputStream.skip(long) 来跳过此填充。

具体来说,它做到了:

public int skipFully(int n) throws IOException {
int total = 0;
int cur;
while (total < n && (cur = (int) in.skip(n - total)) > 0) {
total += cur;
}
return total;
}

在没有线路加密的情况下,这可以正常工作,因为 BufferedInputStreamSocketInputStream 中的 skip 实现的组合至少会跳过 1 个字节调用skip,除非套接字已关闭。

添加CipherInputStream后,这种期望不再成立:如果BufferedInputStream的缓冲区中没有字节,它将调用skip(long) CipherInputStream 上的 code>,如果它位于其缓冲区的末尾,它将跳过 0 个字节(这是允许跳过的)。

因此,Jaybird 可能会跳过太少的 1、2 或 3 个字节,从而导致后续读取读取到错误的数据。最终,这会导致缓冲区大小读取不正确,导致读取阻塞等待更多数据,或者导致 Jaybird 读取错误的操作代码,这将导致异常,并显示以 “不支持”开头的消息或意外的操作代码”

具有类似行为的其他问题的变通方法或解决方案

作为挂起连接的解决方法,您可以使用连接属性 soTimeout 设置套接字读取超时(请参阅 Jaybird Manual, appendix A.2 Other properties )。

问题也可能是 Firebird “只是”无限期地等待锁。要排除 Firebird 等待锁的情况,您还可以更改事务等待模式或超时。 Jaybird 的默认设置是使用无限期等待。

例如,要将读取提交的等待模式更改为无等待,您可以将连接属性 TRANSACTION_READ_COMMITTED 设置为值 read_commissed,rec_version,write,nowait

要使用 wait,但有超时,您可以使用值 read_comfilled,rec_version,write,wait,lock_timeout=5。这将应用 5 秒的锁定超时。

如果您的问题是由于 Firebird 等待另一个事务持有的锁造成的,那么这应该会导致异常,并显示包含 no wait transaction 上的锁冲突 的文本(对于 nowait 选项)或锁定等待事务超时(对于 lock_timeout 选项)。

另请参阅Jaybird Manual, appendix A.3 Transaction isolation levelsJaybird Manual, section 6.4. Transaction Isolation Levels (尽管我现在发现我需要在其中添加更多信息)。

关于java - Jaybird SocketInputStream.socketread0 线程阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58872811/

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