programing

스프링 데이터 MongoRepository 저장(T)이 작동하지 않습니다...가끔씩

oldcodes 2023. 2. 23. 23:04
반응형

스프링 데이터 MongoRepository 저장(T)이 작동하지 않습니다...가끔씩

Angular + Java + Spring Boot + MongoDB 입니다.최근 상당히 많은 조치(읽기: 코드 수정)를 받고 있지만 데이터 액세스 클래스는 거의 변경되지 않았습니다.
그것은 , 만, however, 것.........인 것 .MongoRepository ' i i i i ing suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly suddenly save()DB db db db db db db db 。

mongod.log은, 「이것」 「 」 「 」 「 」 「 」 「 」 「 」save() 삭제:

2018-04-11T15:04:06.840+0200 I COMMAND  [conn6] command pdfviewer.bookData command: find { find: "bookData", filter: { _id: "ID_1" }, limit: 1, singleBatch: true } planSummary: IDHACK keysExamined:1 docsExamined:1 idhack:1 cursorExhausted:1 keyUpdates:0 writeConflicts:0 numYields:1 nreturned:1 reslen:716 locks:{ Global: { acquireCount: { r: 4 } }, Database: { acquireCount: { r: 2 } }, Collection: { acquireCount: { r: 2 } } } protocol:op_query 102ms
2018-04-11T17:30:19.615+0200 I WRITE    [conn7] update pdfviewer.bookData query: { _id: "ID_1" } update: { _class: "model.BookData", _id: "ID_1", config: { mode: "normal", offlineEnabled: true }, metadata: { title: "PDFdePrueba3pag   copia  6 ", ...}, downloaded: false, currentPageNumber: 2, availablePages: 3, bookmarks: [], stats: { _id: "c919e517-3c68-462c-8396-d4ba391762e6", dateOpen: new Date(1523460575872), dateClose: new Date(1523460575951), timeZone: "+2", ... }, ... } keysExamined:1 docsExamined:1 nMatched:1 nModified:1 keyUpdates:0 writeConflicts:1 numYields:1 locks:{ Global: { acquireCount: { r: 2, w: 2 } }, Database: { acquireCount: { w: 2 } }, Collection: { acquireCount: { w: 2 } } } 315ms
2018-04-11T17:30:19.615+0200 I COMMAND  [conn7] command pdfviewer.$cmd command: update { update: "bookData", ordered: false, updates: [ { q: { _id: "ID_1" }, u: { _class: "model.BookData", _id: "ID_1", config: { mode: "normal", offlineEnabled: true }, metadata: { title: "PDFdePrueba3pag   copia  6 ", ...}, downloaded: false, currentPageNumber: 2, availablePages: 3, bookmarks: [], stats: { _id: "c919e517-3c68-462c-8396-d4ba391762e6", dateOpen: new Date(1523460575872), dateClose: new Date(1523460575951), timeZone: "+2", ... }, ... }, upsert: true } ] } keyUpdates:0 writeConflicts:0 numYields:0 reslen:55 locks:{ Global: { acquireCount: { r: 2, w: 2 } }, Database: { acquireCount: { w: 2 } }, Collection: { acquireCount: { w: 2 } } } protocol:op_query 316ms

그렇지 않을 때는 다음과 같습니다.

2018-04-11T18:13:21.864+0200 I NETWORK  [initandlisten] connection accepted from 127.0.0.1:64271 #1 (1 connection now open)
2018-04-11T18:18:51.425+0200 I NETWORK  [initandlisten] connection accepted from 127.0.0.1:64329 #2 (2 connections now open)
2018-04-11T18:19:06.967+0200 I NETWORK  [initandlisten] connection accepted from 127.0.0.1:64346 #3 (3 connections now open)

tail -f1 디버깅 중에 로그 파일에서 코드가 호출될 때 바로 연결이 나타나는 것을 보았습니다.findById() ★★★★★★★★★★★★★★★★★」save()할 수 것 같아요. DB에 접속할 수 있을 것 같아요.

관련 Java 코드입니다(대상의 Java 코드입니다.

/* BookData.java */
@Document
public class BookData {

    @Id private String id;
    // Some more non-Id Strings...
    private Config config;
    private Metadata metadata;
    private Boolean downloaded;
    private Integer currentPageNumber;
    private int availablePages;
    private List<Bookmark> bookmarks;
    private StatsModel stats;

    @Transient private byte[] contents;

    public BookData() {}

    // getters and setters
}

/* BookDataRepository.java */
// MongoRepository comes from spring-boot-starter-parent-1.4.5.RELEASE
public interface BookDataRepository extends MongoRepository<BookData, String> {
    BookData findById(String id);
}

/* BookDataServiceImpl.java */
public BookData updateBookData(String id, BookData newData) {
    final BookData original = bookDataRepository.findById(id);
    if (original == null) {
        return null;
    }
    original.setCurrentPageNumber(Optional.ofNullable(newData.getCurrentPageNumber()).orElseGet(original::getCurrentPageNumber));
    // similar code for a couple other fields

    return bookDataRepository.save(original);
}

디버깅을 하면서 이 부분을 수백 번 확인했는데 모든 것이 정상인 것 같습니다.

  • findById(id)된 「예상치 않은 것」을 올바르게 반환합니다.BookData original체크해주세요
  • newData업데이트에 이 포함되어.체크박스를 켜겠습니다크크스를를켜켜켜켜켜
  • save(original),original되었습니다.newData: 체크: " "
  • save()체크박스를 켜겠습니다
  • save() 것을 BookData된 값:
  • 후에save() ,,, adb.bookData.find()query in Mongo Shell은 값이 갱신되었음을 나타냅니다.fail
  • 후에save(),BookData 콜에 findById()에는 fail(실패할 수도 있고 아닐 수도 있습니다)의 갱신된 값이 포함되어 있습니다.

것 .flush(), JPA를 호출할 수 saveAndFlush()★★★★★★ 。

왜 이런 일이 일어나는지 짐작 가는 거라도?

편집: 버전(요구에 따라):

  • 자바 8
  • 스프링 부트 1.4.5
  • MongoDB 3.2.6
  • 윈도 10

저도 포함시켰습니다.BookDataabovedisclossible을 합니다.

MongoDB는 본질적으로 캐시 저장소입니다. 즉, 컨텐츠가 최신이거나 정확하다고 보장되지 않습니다.플래시 타임의 설정 옵션은 찾을 수 없습니다(단, DB 자체에서 설정 가능).MongoDB는 기능을 추가했기 때문에 fast+dirty 또는 slow+clean을 선택할 수 있습니다.이러한 종류의 문제가 발생하고 있는 경우는, 이 「신선함」요소가 가장 큰 문제일 가능성이 있습니다.(분산되어 있지 않은 경우에도 요구 확인 응답과 커밋된 요구 사이에는 타이밍 차이가 있습니다.)

다음은 "깨끗한 판독치"와 관련된 게시 링크입니다(아래 인용문의 요점).

http://www.dagolden.com/index.php/2633/no-more-dirty-reads-with-mongodb/

MongoDB 사용자는 다음 중 하나의 그룹에 자기 자신(또는 적어도 애플리케이션 액티비티)을 배치할 것을 권장합니다.

"저레이텐시를 원합니다"– 빠른 속도라면 지저분한 판독도 문제 없습니다.w=1을 사용하고 해당 문제를 '로컬'로 읽습니다(기본 설정은 다음과 같습니다).「일관성을 요구하고 싶다」– 레이텐시 또는 약간 오래된 데이터를 사용하더라도, 지저분한 판독은 문제 없습니다.w='로 사용하고 불만 사항 '로 판독하십시오.MongoDB v1.2.0 사용;

my $mc = MongoDB->connect(
    $uri,
    {
        read_concern_level => 'majority',
        w => 'majority',
    }
);

도움이 될 수도 있고 안 될 수도 있는 추가 독서

갱신하다

멀티 스레드 환경에서 실행할 경우 스레드가 다른 스레드의 업데이트를 짓밟지 않도록 하십시오.시스템 로깅레벨 또는 쿼리 로깅레벨을 5로 설정하면 이 문제가 발생하는지 확인할 수 있습니다.https://docs.mongodb.com/manual/reference/log-messages/ #log-syslog-configure-verbority

문제는 해결됐습니다.
JS 클라이언트에서 Java 백엔드의 다른 엔드포인트로의 다른 비동기 호출이 원래 값으로 다른 스레드의 업데이트된 문서를 덮어쓰고 있었습니다.

이 「」를 호출하고 .findById저장하기 전에.문제는 그들이 동시에 그렇게 했기 때문에, 그들은 원래와 같은 값을 얻고 있었다는 것이다.
각자가 를 건다.save결과적으로 다른 스레드가 변경 사항을 효과적으로 덮어쓰게 됩니다.
각 콜은 관련된 변경 필드만 로그되어 있기 때문에 한쪽이 다른 쪽의 변경을 덮어쓰고 있는 것을 깨닫지 못했습니다.

systemLog.verbosity: 3의 ★★★★★★★★★★★★★★★★★★★★★.config.cfg따라서 모든 작업을 기록했으며, 2개의 서로 다른 쓰기 작업이 동시에(~500ms 간격) 발생하지만 서로 다른 값을 사용하고 있는 것이 분명했습니다.
그럼 이건 그냥 그 집을 옮기는 문제였군요findByIdsaveJS 콜이 순서대로 행해지고 있는 것을 확인합니다(어느쪽의 약속을 다른 쪽에 의존시키는 것으로).

돌이켜 생각해보면, 만약 내가 이걸 썼다면 아마 이런 일은 일어나지 않았을 것이다.MongoOperations ★★★★★★★★★★★★★★★★★」MongoTemplate, 싱글, 싱글, 을 제공합니다.update ★★★★★★★★★★★★★★★★★」findAndModify 조작도 하게 하는 MongoRepository(3단계에 .find엔티티를 합니다.save전체 문서 작업을 수행합니다.


첫 "무브"가에 들지 않았습니다: "무브"는 "무브"입니다.findById 곳에 있는 것 같아요.save" 어프로치에서는 결국 옳다고 생각되는 것을 실행해, 의 보다 세밀한 API를 사용한 커스텀 보존 방법을 실장했습니다.최종 코드:

/* MongoRepository provides entity-based default Spring Data methods */
/* BookDataRepositoryCustom provides field-level update methods */
public interface BookDataRepository extends MongoRepository<BookData, String>, BookDataRepositoryCustom {

    BookData findById(String id);

}

/* Interface for the custom methods */
public interface BookDataRepositoryCustom {

    int saveCurrentPage(String id, Integer currentPage);
}

/* Custom implementation using MongoTemplate. */
@SuppressWarnings("unused")
public class BookDataRepositoryImpl implements BookDataRepositoryCustom {
    @Inject
    MongoTemplate mongoTemplate;

    @Override
    public int saveCurrentPage(String id, Integer currentPage) {
        Query query = new Query(Criteria.where("_id").is(id));
        Update update = new Update();
        update.set("currentPage", currentPage);

        WriteResult result = mongoTemplate.updateFirst(query, update, BookData.class);

        return result == null ? 0 : result.getN();
    }
}

// Old code: get entity from DB, update, save. 3 steps with plenty of room for interferences.
//        BookData bookData = bookDataRepository.findById(bookDataId);
//        bookData.setCurrentPage(currentPage);
//        bookDataRepository.save(bookData);
// New code: update single field. 1 step, 0 problems.
        bookDataRepository.saveCurrentPage(bookDataId, currentPage);

함으로써 각는 '''를 사용할 수 있습니다.update에 따라 MongoTemplate필드를 엔티티 의 엔티티 기반 엔티티 엔티티, 엔티티 기반 엔티티 기반 엔티티, 엔티티 기반 엔티티 필드를 유지합니다.MongoRepository 작성, 새로운 엔티티 작성 ,findBy,이 달린 ''', '''@Query

언급URL : https://stackoverflow.com/questions/49780827/spring-data-mongorepository-savet-not-working-sometimes

반응형