我正在使用与Firebird的JDBC连接。
<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?
感谢您的回答。
编辑:
这是线程阻塞的屏幕:
最佳答案
在您的情况下,根本原因是在firebird.conf中启用有线加密(设置WireCrypt = Enabled
)时,Jaybird 3.0.4至3.0.7(和4.0.0-beta-1)中的Firebird 3(和4)中存在错误。 。
我以前只在Jaybird 4的测试按特定顺序运行时才看到Jaybird 4的问题,并且由于该版本尚未发布,因此我没有优先考虑查找根本原因。
在您的帮助下(再次感谢!),我能够确定问题所在。现在,此错误已在Jaybird 3.0.8中修复,可从Firebird: JDBC Driver获得。
错误说明
Firebird有线协议中的某些类型的缓冲区(例如,列数据)以字节填充为四的倍数。 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;
}
这在没有有线加密的情况下效果很好,因为除非关闭套接字,否则
skip
和BufferedInputStream
中SocketInputStream
实现的组合对于每次对skip
的调用至少会跳过1个字节。添加
CipherInputStream
时,这种期望不再成立:如果BufferedInputStream
的缓冲区中没有字节,它将在skip(long)
上调用CipherInputStream
,如果在其缓冲区的末尾,它将跳过0个字节(skip
允许)。结果,Jaybird可能会跳过太少的1个,2个或3个字节,这导致后续的读取操作读取了错误的数据。最终,这将导致错误地读取缓冲区大小,导致读取阻塞以等待更多数据,或者将导致Jaybird读取错误的操作代码,这将导致异常,并以“不支持或意外操作开头”消息码”。
行为类似的其他问题的解决方法或解决方案
作为挂起连接的一种解决方法,可以使用连接属性
soTimeout
设置套接字读取超时(请参见Jaybird Manual, appendix A.2 Other properties)。问题还可能是Firebird在锁上无限期地“只是”等待。要排除Firebird等待锁定,您还可以更改事务等待模式或超时。 Jaybird的默认设置是使用无限期等待。
例如,要将读取提交的等待模式更改为不等待,可以将连接属性
TRANSACTION_READ_COMMITTED
设置为值read_committed,rec_version,write,nowait
。要使用等待但有超时的情况,可以使用值
read_committed,rec_version,write,wait,lock_timeout=5
。这将应用5秒钟的锁定超时。如果您的问题是由于Firebird等待另一个事务持有的锁而引起的,则这将导致异常,其中包含在无等待事务(对于
nowait
选项)上的锁冲突或在等待事务上的锁超时(为lock_timeout
选项)。另请参见Jaybird Manual, appendix A.3 Transaction isolation levels和Jaybird Manual, section 6.4. Transaction Isolation Levels(尽管现在我需要在其中添加更多信息)。