Postgres JDBC线程卡在java.net.SocketInputStream.socketRead0上,即使定



我们正在使用Wildfly 16上的Java应用程序,该应用程序与使用EclipseLink的Postgres 9.4数据库相连。应用程序服务器配置为使用连接池。该应用程序在夜间将项目索引到 Solr 实例,我们不时遇到阻塞线程的问题。似乎数据库查询毕竟没有返回。我们在 持久性单元,这似乎不起作用。我们在持久性中添加了以下条目.xml:

<property name="javax.persistence.query.timeout" value="30000"/>

系统使用的是Java 11 jre。我们使用 docker wildfly 映像 (https://hub.docker.com/r/jboss/wildfly/dockerfile) 作为基础,但在其他应用程序服务器和 Java 版本中也看到了这个问题。

线程转储显示一些详细信息。进程正在运行数小时。我们预计 30 年代后会抛出例外。我们缺少什么?

"索引器线程" #181 守护程序 prio=5 os_prio=0 cpu=3845600.45ms 已用=124856.57s tid=0x000000000a51b800 nid=0x12d 可运行 [0x00007fb51dcb9000]  java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0(java.base@11.0.4/Native Method) at java.net.SocketInputStream.socketRead(java.base@11.0.4/SocketInputStream.java:115) at java.net.SocketInputStream.read(java.base@11.0.4/SocketInputStream.java:168) at java.net.SocketInputStream.read(java.base@11.0.4/SocketInputStream.java:140) at org.postgresql.core.VisibleBufferedInputStream.readMore(VisibleBufferedInputStream.java:146) at org.postgresql.core.VisibleBufferedInputStream.ensureBytes(VisibleBufferedInputStream.java:115) at org.postgresql.core.VisibleBufferedInputStream.read(VisibleBufferedInputStream.java:71)at org.postgresql.core.PGStream.ReceiveChar(PGStream.java:283) at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1719) at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:173) - lock (a org.postgresql.core.v3.QueryExecutorImpl) at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:622) at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:472) at org.postgresql.jdbc.PgStatement.executeUpdate(PgStatement.java:429) at jdk.internal.reflect.GeneratedMethodAccessor24.invoke(Unknown Source) at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@11.0.4/DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(java.base@11.0.4/Method.java:566) at org.postgresql.ds.PGPooledConnection$StatementHandler.invoke(PGPooledConnection.java:466) at com.sun.proxy.$Proxy 69.executeUpdate(未知来源)at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:537) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:898) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:970) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:640) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:567) at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:2096) at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:311) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:275)at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:261) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.updateObject(DatasourceCallQueryMechanism.java:832) at org.eclipse.persistence.internal.queries.StatementQueryMechanism.updateObject(StatementQueryMechanism.java:437) at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.updateObjectForWriteWithChangeSet(DatabaseQueryMechanism.java:1093) at org.eclipse.persistence.queries.UpdateObjectQuery.executeCommitWithChangeSet(UpdateObjectQuery.java:86) at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:316) at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:60) at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:914)at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:813) at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:110) at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:87) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2981) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1895) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1877) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1827) at org.eclipse.persistence.internal.sessions.CommitManager.commitChangedObjectsForClassWithChangeSet(CommitManager.java:275) at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:133)at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:4387) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1493) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1583) at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:280) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1220) at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:136) at com.freiheit.vrms.persistence.SystemObjectPersistenceService.createOrUpdateNextIndexerRun(SystemObjectPersistenceService.java:2134) at com.freiheit.vrms.service.search.SearchService.attributeIndexFields(SearchService.java:322)at com.freiheit.vrms.service.search.SearchService.indexObjectInternal(SearchService.java:848) at com.freiheit.vrms.service.search.SearchService.indexObjectInForeground(SearchService.java:752) - 锁定(java.lang.Object) at com.freiheit.vrms.service.search.SearchService.indexObjectInForeground(SearchService.java:746) at com.freiheit.vrms.service.search.IndexJob$JobType$2.execute(IndexJob.java:60) at com.freiheit.vrms.service.search.IndexJob.execute(IndexJob.java:104) at com.freiheit.vrms.service.search.IndexQueue.handleMessage(IndexQueue.java:243) at com.freiheit.vrms.service.search.IndexQueue.run(IndexQueue.java:155) at java.lang.Thread.run(java.base@11.0.4/Thread.java:834)  锁定的可拥有同步器: - (a java.util.concurrent.locks.ReentrantLock$FairSync)

EDIT:我想添加一些额外的代码,这会导致线程冻结。

final EntityTransaction transaction = em.getTransaction();
transaction.begin();
updateNextIndexerRun( em, id, nextIndexerRun );
transaction.commit();

如上图所示,螺纹卡在transaction.commit()线上。这个片段每天被调用数千次,并且大多数时候不会造成任何麻烦。将在其中保存数据的表一次有 ~20000 个条目。方法updateNextIndexerRun定义如下:

private void updateNextIndexerRun( final EntityManager em, final Long id, @Nullable final Calendar newNextIndexerRun ) {
final NextIndexerRunDBBean oldNextIndexerRun = getNextIndexerRun( em, id );
if ( newNextIndexerRun == null && oldNextIndexerRun != null ) {
em.remove( oldNextIndexerRun );
} else if ( newNextIndexerRun != null ) {
if ( oldNextIndexerRun == null ) {
em.persist( new NextIndexerRunDBBean( id, newNextIndexerRun ) );
} else {
em.merge( new NextIndexerRunDBBean( id, newNextIndexerRun ) );
}
}
}

查询本身在 30 秒内运行,因此不会应用超时。现在从这里我们看到

上面的 JPQL 查询将在 50 毫秒后超时,除非 在超时阈值之前获取结果集。

您已经在读取结果集,但它太大或读取速度不够快时出现问题。

最新更新