programing

스프링 부트 페일 세이프 청소(집합)가 발생하는 이유

itmemos 2023. 9. 9. 09:04
반응형

스프링 부트 페일 세이프 청소(집합)가 발생하는 이유

아래 예외와 관련된 다음 엔티티가 있는 Java Spring Boot 애플리케이션이 있습니다.

SP제품

@Entity
@Table(
        name = "product",
        indexes = @Index(
                name = "idx_asin",
                columnList = "asin",
                unique = true
        )
)
public class SProduct implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    @Column(name = "asin", unique = false, nullable = false, length = 10)
    private String asin;
    @Column(name = "rootcategory")
    private Long rootcategory;
    @Column(name = "imageCSV", unique = false, nullable = true, length = 350)
    private String imagesCSV;
    @Column(name = "title", unique = false, nullable = true, length = 350)
    private String title;
    private Date created;
    @OneToMany(fetch = FetchType.EAGER, mappedBy = "mainProduct", cascade = CascadeType.ALL)
    private Set<FBT> fbts;
    @OneToOne(fetch = FetchType.EAGER, mappedBy = "downloadProductId", cascade = CascadeType.ALL)
    private Download download;

FBT

@Entity
@Table(
    name = "fbt",
    uniqueConstraints={@UniqueConstraint(columnNames = {"main_product_id" , "collection"})},
    indexes = {@Index(
        name = "idx_main_product_id",
        columnList = "main_product_id",
        unique = false),
        @Index(
        name = "idx_product_fbt1id",
        columnList = "product_fbt1_id",
        unique = false),
        @Index(
        name = "idx_product_fbt2id",
        columnList = "product_fbt2_id",
        unique = false)
        }
)
public class FBT implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    @ManyToOne
    @JoinColumn(name = "main_product_id")
    private SProduct mainProduct;
    @ManyToOne
    @JoinColumn(name = "product_fbt1_id")
    private SProduct sproductFbt1;
    @ManyToOne
   
    @JoinColumn(name = "product_fbt2_id")
    private SProduct sproductFbt2;
    @Column(name = "bsr", nullable = false)
    private int bsr;
    private Date collection;

제 fbt 저장소에 다음과 같은 문의가 있었습니다.

  FBT findByMainProductAndCollection(SProduct mainProduct,Date collection);

이로 인해 메인 Product 및 컬렉션의 데이터베이스에 데이터가 존재할 경우 다음 메시지가 출력 예외가 발생하지만 그렇지 않으면 null을 반환합니다.

  <message>HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@69b7fcfc&lt;rs=HikariProxyResultSet@325408381 wrapping com.mysql.jdbc.JDBC42ResultSet@108693fa&gt;</message>
  <message>HHH000160: On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [1] entries</message>
  <message>HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@47c40535&lt;rs=HikariProxyResultSet@2005129089 wrapping com.mysql.jdbc.JDBC42ResultSet@9894f70&gt;</message>
  <message>HHH000160: On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [1] entries</message>
  <message>HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@5b0cd175&lt;rs=HikariProxyResultSet@1598144514 wrapping com.mysql.jdbc.JDBC42ResultSet@6a7ff475&gt;</message>
  <message>HHH000160: On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [1] entries</message>
  <message>HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@f67e2cc&lt;rs=HikariProxyResultSet@319200129 wrapping com.mysql.jdbc.JDBC42ResultSet@215b8a6&gt;</message>
  <message>HHH000160: On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [1] entries</message>
  <message>HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@5961afc0&lt;rs=HikariProxyResultSet@1772496904 wrapping com.mysql.jdbc.JDBC42ResultSet@5956a59b&gt;</message>
  <message>HHH000160: On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [1] entries</message>
  <message>HHH000100: Fail-safe cleanup (collections) : 

데이터가 존재하는지 여부만 확인하면 되므로 위의 내용을 버리고 @query를 작성하여 카운트하기로 결정하였으며 이로 인해 @query를 사용하기 위해 모든 코드를 변경해야 한다는 생각이 들었습니다.

 @Query("select count(*) as count from FBT where main_product_id = :id and collection= :collection")
    int countByMainProductIdAndCollection(@Param("id") long id, @Param("collection") Date collection);

제품이 이미 데이터베이스에 존재하는 경우에도 마찬가지로 한 SP 제품의 데이터베이스 업데이트 시에도 마찬가지로 무작위로 발생합니다.

SProductRepo.saveAndFlush(s);

나는 같은 코드를 실행하는 11개의 어플리케이션이 위의 메시지와 함께 임의의 간격으로 종료됨에 따라 임의로 말합니다.코드에 의해 생성된 예외는 없으며 성공적인 데이터베이스 업데이트에 대한 10000개의 예외가 실패로 이어지는 동일한 코드에서 발생합니다.이전에 작동했던 데이터베이스를 업데이트하려고 하면 코드가 중지됩니다.

""2018-12-28 00:56:06 [KeepaAPI-RetryScheduler] WARN  org.hibernate.engine.loading.internal.LoadContexts - HHH000100: Fail-safe cleanup (collections) : org.hibernate.eng
ine.loading.internal.CollectionLoadContext@5c414639<rs=HikariProxyResultSet@1241510017 wrapping Result set representing update count of 13>
""2018-12-28 00:56:06 [KeepaAPI-RetryScheduler] WARN  org.hibernate.engine.loading.internal.CollectionLoadContext - HHH000160: On CollectionLoadContext#cleanup, localLoa
dingCollectionKeys contained [1] entries
""2018-12-28 00:56:06 [KeepaAPI-RetryScheduler] WARN  org.hibernate.engine.loading.internal.LoadContexts - HHH000100: Fail-safe cleanup (collections) : org.hibernate.eng
ine.loading.internal.CollectionLoadContext@5595c065<rs=HikariProxyResultSet@2140082434 wrapping Result set representing update count of 14>
""2018-12-28 00:56:06 [KeepaAPI-RetryScheduler] WARN  org.hibernate.engine.loading.internal.CollectionLoadContext - HHH000160: On CollectionLoadContext#cleanup, localLoa
dingCollectionKeys contained [1] entries
""2018-12-28 00:56:06 [KeepaAPI-RetryScheduler] WARN  org.hibernate.engine.loading.internal.LoadContexts - HHH000100: Fail-safe cleanup (collections) : org.hibernate.eng
ine.loading.internal.CollectionLoadContext@2956fe24<rs=HikariProxyResultSe

또한 SP product findByAsin(Stringasin) 쿼리는 데이터베이스의 쿼리가 완벽하게 작동하고 스프링 부트에서 작동하는 경우에도 동일한 문제를 야기합니다.

mysql> select * from product where asin="B004FXJOQO";
| id | asin       | created    | imagecsv                                                                        | rootcategory | title                                                                                                        |  9 | B004FXJOQO | 2018-08-04 | 41T0ZwTvSSL.jpg,61V90AZKbGL.jpg,51AdEGCTZqL.jpg,51LDnCYfR0L.jpg,71bbIw43PjL.jpg |       228013 | Dual Voltage Tester, Non Contact Tester for High and Low Voltage with 3-m Drop Protection Klein Tools NCVT-2 |
1 row in set (0.00 sec)

제가 알고 싶은 것은 이런 종류의 메시지가 생성되는 일반적인 이유는 무엇입니까?

코드에서 마지막으로 실행된 삽입문에 대한 캐치 문을 시도해도 응용 프로그램을 중지하는 이유는 무엇입니까?

메시지가 생성되는 정확한 이유를 파악하는 데 유용한 로그 디버깅 설정이 있습니까?

이 기능을 끄거나 제어할 수 있는 방법이 있습니까?

  <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <maven-dependency-plugin.version>2.10</maven-dependency-plugin.version>
        <maven.test.skip>true</maven.test.skip>
    </properties>
    <repositories>
        <repository>
            <id>Keepa</id>
            <name>Keepa Repository</name>
            <url>https://keepa.com/maven/</url>
        </repository>
    </repositories>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency> 
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-integration</artifactId>
        </dependency>
        
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4.7</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-compress</artifactId>
            <version>1.18</version>
        </dependency>
        <dependency>
            <groupId>com.google.api-client</groupId>
            <artifactId>google-api-client</artifactId>
            <version>1.22.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.oauth-client</groupId>
            <artifactId>google-oauth-client-jetty</artifactId>
            <version>1.22.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.apis</groupId>
            <artifactId>google-api-services-oauth2</artifactId>
            <version>v1-rev120-1.22.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.oauth-client</groupId>
            <artifactId>google-oauth-client-java6</artifactId>
            <version>1.22.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.oauth-client</groupId>
            <artifactId>google-oauth-client</artifactId>
            <version>1.22.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.apis</groupId>
            <artifactId>google-api-services-gmail</artifactId>
            <version>v1-rev48-1.22.0</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>1.5.0</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-nop</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.54</version>
        </dependency>
        <dependency>
            <groupId>com.myjeeva.digitalocean</groupId>
            <artifactId>digitalocean-api-client</artifactId>
            <version>2.16</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
        </dependency>
        <dependency>
            <groupId>com.keepa.api</groupId>
            <artifactId>backend</artifactId>
            <version>LATEST</version>
        </dependency>
        <dependency>
            <groupId>org.jdeferred</groupId>
            <artifactId>jdeferred-core</artifactId>
            <version>1.2.6</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>22.0</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build

메모리를 1gb에서 2gb로 늘렸는데 메모리가 지금의 30%밖에 안 됩니다.

무엇이 문제인지에 대한 생각은 없습니까?

제 경우는 개체들이 서로의 해시코드를 재귀적으로 호출하기 때문에 롬복을 사용하면 제거하고 직접 만듭니다.두 개의 해시 코드의 메소드에 디버거의 중단점을 둡니다.당신은 그들이 서로를 부르는 것을 보게 될 것입니다.예를 들어 첫 번째 엔티티의 해시 코드 메서드 두 번째 엔티티의 링크에서 제거합니다.

세트를 사용할 때는 이 문제가 발생했지만 목록으로 변경할 때는 해결된 문제를 사용해야 합니다.

  private List<FBT> fbts;

첫째, 동면 오류입니다.org.hibernate.engine스프링부츠와는 아무 상관이 없습니다

HQL 쿼리를 사용하여 수만 개의 엔티티와 같이 많은 양의 데이터를 가져올 경우 이러한 문제가 발생할 수 있습니다.

이는 자식 엔티티가 많은 일대일 연결을 매핑한 경우와 양방향 매핑으로 인해 결과 집합이 무한히 복제되는 경우에도 마찬가지입니다.

고성능 JPA 팁은 아래 링크를 참조하십시오.

https://vladmihalcea.com/14-high-performance-java-persistence-tips/

제 경우엔 "java.lang"이란 말을 들었습니다.StackOverflowError: null"(이전에는 여러 "Fail-safe cleanup (collections)" 로그 메시지도 있음)은 양방향 관계가 @ManyToOne 및 @OneToMany인 특정 엔티티에서 JPA 저장 메서드를 실행할 때 발생합니다.이상하게도 Oracle과 Postgre에서만 실패하고 있었습니다.SQL이지만 MySQL, MariaDB 및 SQL Server에서 잘 작동합니다.

따라서 문제는 @OneToMany 엔티티에 있는 해시코드를 사용한 롬복이었습니다.

레벨 클래스의 해당 엔티티에서 이 주석을 설정하여 해결했습니다.

@EqualsAndHashCode(= "이름 속성 제외)이 클래스에서 "One To Many")

한번 해보시겠어요?@Fetch(value = SELECT)?

@OneToMany(fetch = FetchType.EAGER, mappedBy = "mainProduct", cascade = CascadeType.ALL)
@Fetch(value=FetchMode.SELECT)
private Set<FBT> fbts;

애플리케이션에 엄청난 양의 데이터를 로드하는 것 같습니다.

메소드

FBT findByMainProductAndCollection(SProduct mainProduct,Date collection);

일치하는 모든 데이터를 로드합니다.그러나 모든 데이터 대신 정확하게 데이터 개수를 반환하는 쿼리만 사용하면 됩니다.

한가지 방법은 당신이 언급한 쿼리를 사용하는 것이고 다른 방법은

Long countByMainProductAndCollection(SProduct mainProduct, Date collection);

아니면

Boolean existsByMainProductAndCollection(SProduct mainProduct, Date collection)

제 경우에는 자동 발전기를 이용해서Repository돌아온 메소드List<MyData>. 2000개의 개체가 최대 절전 모드에 너무 많은 것으로 나타났습니다.반품하는 방법으로 교체하여 문제를 해결하였습니다.Stream<MyData>, 그런 다음 엔티티를 수작업 구조물에 매핑합니다.MyDataDetached.

언급URL : https://stackoverflow.com/questions/53540056/what-causes-spring-boot-fail-safe-cleanup-collections-to-occur

반응형