Я использую mssql-jdbc-12.2.0.jre8.jar и HikariCP-4.0.3.jar для подключения к базе данных Microsoft SQL Server.
Версия SQL Server: Microsoft SQL Server 2012 - 11.0.5548.0 (X64) Sep 6 2014 17:19:28 Copyright (c) Microsoft Corporation Enterprise Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: ) (Hypervisor)
Спящая версия: hibernate-core-5.6.11.Final
JRE-версия: jre1.8.0_281
Версия Apache Tomcat: 9.0.71
Версия Springboot: 2.7.4
Конфигурация Spring DataSource:
spring.datasource.url=jdbc:sqlserver://mydatabaseServer:51803;databaseName=mydatabaseName;encrypt=false;trustServerCertificate=true;socketTimeout=60000
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.password = mypassword
spring.datasource.testWhileIdle = true
spring.datasource.test-on-borrow=true
spring.datasource.validationQuery = SELECT 1
spring.datasource.sql-script-encoding=UTF-8
spring.datasource.username = myusername
spring.datasource.hikari.pool-name=myPool
spring.datasource.hikari.maximum-pool-size=300
spring.datasource.hikari.connectionTimeout=80000
spring.datasource.hikari.max-lifetime=300000
spring.datasource.hikari.idle-timeout=60000
spring.datasource.hikari.leakDetectionThreshold=300000
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.SQLServer2012Dialect
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
spring.jpa.open-in-view=false
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
Запрос, вызывающий проблему, возвращает максимум 10 строк следующим образом:
@Repository
@Transactional(readOnly = true)
@Log4j2
public class SearchService {
@PersistenceContext
private EntityManager entityManager;
public List<Request> searchRequests(SearchModel searchModel, int pageNumber) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Request> criteriaQuery = criteriaBuilder.createQuery(Request.class);
Root<Request> requestRoot = criteriaQuery.from(Request.class);
requestRoot.alias("r");
Predicate predicate = createConditions(requestRoot, criteriaBuilder, searchModel);
criteriaQuery.select(requestRoot);
Order orderBy = criteriaBuilder.desc(requestRoot.get("id"));
String orderByProperty = searchModel.getOrderBy();
criteriaQuery.where(predicate).orderBy(orderBy);
// pageSize is 10
// searchModel.getMaxResult() = 10
// for pageNumber 1 startFrom will be 0 and maxResult will be 10
int startFrom = (pageNumber - 1) * searchModel.getPageSize();
List<Request> result = entityManager.createQuery(criteriaQuery).setMaxResults(searchModel.getMaxResult())
.setFirstResult(startFrom).getResultList();
return result;
}
}
Вышеупомянутая установка отлично работает долгое время, но в последнее время я иногда получаю множество следующих исключений: com.microsoft.sqlserver.jdbc.sqlserverexception: the stream is closed
на линии :
entityManager.createQuery(criteriaQuery).setMaxResults(searchModel.getMaxResult())
.setFirstResult(startFrom).getResultList();
Это переводится как:
SELECT * FROM request ORDER BY id OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;
при выполнении этого запроса непосредственно из SQL Server требуется 10 мс и когда поток закрывается, возникает проблема, в инструментах мониторинга я вижу, что он закрывается в этом запросе несколько раз!
Примечание. Объект/таблица запроса, из которой я выбираю, не имеет отношений Eager и не имеет двоичных столбцов, но имеет два столбца varchar (MAX), а максимальная достигнутая длина составила 5368.
что может быть причиной этой проблемы? может ли это быть связано с приложением или проблемой с базой данных/сервером Windows?




Исключение «поток закрыт»… довольно расплывчато.
Предполагая, что проблем с сетью нет, а журналы SQL Server не показывают никаких других более подробных сообщений об ошибках, или у самого сервера нет проблем с ЦП/памятью/дисковым пространством, вы можете подумать:
Проверьте настройки пула соединений HikariCP. Возможно, вы захотите настроить параметры max-lifetime, idle-timeout и leakDetectionThreshold, чтобы соединения не закрывались преждевременно или удерживались слишком долго.
Оптимизируйте свой запрос. Несмотря на то, что сам запрос работает хорошо при выполнении непосредственно на SQL Server, вы все равно можете попытаться оптимизировать запрос, добавив соответствующие индексы в таблицу Request или используя разбиение на страницы с более эффективным подходом, таким как с помощью пагинации на основе набора ключей.
Попробуйте также поймать исключение с более подробной информацией, как, например, (из «Как поймать ИСКЛЮЧЕНИЯ Hibernate SQL ВЕСНОЙ»):
import javax.persistence.PersistenceException;
import org.hibernate.exception.JDBCConnectionException;
import org.springframework.dao.DataAccessException;
@Repository
@Transactional(readOnly = true)
@Log4j2
public class SearchService {
@PersistenceContext
private EntityManager entityManager;
public List<Request> searchRequests(SearchModel searchModel, int pageNumber) {
List<Request> result = new ArrayList<>();
try {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Request> criteriaQuery = criteriaBuilder.createQuery(Request.class);
Root<Request> requestRoot = criteriaQuery.from(Request.class);
requestRoot.alias("r");
Predicate predicate = createConditions(requestRoot, criteriaBuilder, searchModel);
criteriaQuery.select(requestRoot);
Order orderBy = criteriaBuilder.desc(requestRoot.get("id"));
String orderByProperty = searchModel.getOrderBy();
criteriaQuery.where(predicate).orderBy(orderBy);
int startFrom = (pageNumber - 1) * searchModel.getPageSize();
result = entityManager.createQuery(criteriaQuery).setMaxResults(searchModel.getMaxResult())
.setFirstResult(startFrom).getResultList();
} catch (PersistenceException | DataAccessException e) {
if (e.getCause() instanceof JDBCConnectionException) {
log.error("JDBC connection exception occurred: {}", e.getMessage(), e);
} else {
log.error("An exception occurred while executing the search query: {}", e.getMessage(), e);
}
} catch (Exception e) {
log.error("An unexpected exception occurred while executing the search query: {}", e.getMessage(), e);
}
return result;
}
}
Я завернул выполнение запроса в блок try-catch, чтобы перехватывать любые PersistenceException, DataAccessException или другие общие исключения. Если происходит JDBCConnectionException, оно будет зарегистрировано с определенным сообщением. Для других исключений будет зарегистрировано более общее сообщение об ошибке.
Это должно помочь вам определить и диагностировать любые проблемы, которые могут возникнуть во время выполнения запроса.
Ошибка, которую вы видите, предполагает, что соединение с SQL Server теряется либо из-за проблемы с сетью, либо из-за проблемы с конфигурацией пула соединений с базой данных.
Вот несколько вещей, на которые вы, возможно, захотите обратить внимание:
Database Connection Pooling: HikariCP — очень надежное соединение
pool и необычно сталкиваться с такими проблемами.
Однако возможно, что некоторые параметры конфигурации могут быть не
оптимально для вашего варианта использования. можно попробовать изменить конфигурацию
настройки HikariCP:max-lifetime: Это свойство определяет максимальное время жизни
соединение в пуле. Как только соединение превысит этот порог,
он будет удален из пула. Значение 0 указывает на отсутствие максимального
время жизни (бесконечное время жизни), что не рекомендуется. По умолчанию
значение 1800000 (30 минут). Ваша текущая стоимость 300000 (5
минут), что может быть слишком мало. Можно попробовать увеличить.idle-timeout: Это свойство управляет максимальным количеством времени, которое
соединение может бездействовать в пуле. Значение по умолчанию
600000 (10 минут). Ваше текущее значение составляет 60000 (1 минута), что
также может быть слишком низким. Можно попробовать увеличить.Database Server: проверьте, нет ли проблем с базой данных
сам сервер. Могут быть проблемы с сетью или сервер может быть
преждевременное закрытие соединений. Ваш администратор базы данных должен быть в состоянии помочь с
этот.Network Issues: Проблемы с сетью также могут вызывать эту ошибку. Если
между вашим приложением и
сервер базы данных, это может привести к закрытию потока. Проверять
для любых сетевых проблем на пути между вашим приложением и
база данных.JDBC Driver: Драйвер JDBC также может быть фактором. Попробуйте обновить до
последняя версия драйвера JDBC для SQL Server, если вы еще не
уже.Query Execution Time: Хотя вы упомянули, что выполнение запроса
быстро при запуске непосредственно на сервере, могут быть сценарии, когда
это занимает больше времени. Это потенциально может привести к тайм-аутам. Ты можешь
профилируйте свой запрос, чтобы он всегда выполнялся в разумные сроки.Это сложная проблема для отладки, поскольку она носит прерывистый характер. Возможно, вам придется попробовать несколько из этих предложений, чтобы увидеть, поможет ли какое-либо из них. Не забудьте проверить журналы вашего сервера, как для вашего сервера приложений, так и для SQL Server, так как они могут дать больше информации о том, что вызывает проблему.
Еще один сгенерированный ответ...