<aside>

  1. 문제 상황 </aside>
@Entity
@Table(name = "p_posts")
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Post extends BaseEntity {

    public void incrementViews(){
        this.views++;
    }
}
 @Transactional
    public PostResponseDto getPost(UUID postId) {
        Post post = postRepository.findByPostId(postId)
                .orElseThrow(() -> new GlowGlowException(GlowGlowError.POST_NO_EXIST));

        post.incrementViews();

        return PostResponseDto.of(post);
    }

<aside>

  1. 문제 원인 </aside>

정리하자면, 문제의 이유는 트랜잭션 안에서 Read ➡️  Update ➡️  Save의 순서로 흘러갔고, 여러 트랜잭션이 동시에 Read하여 같은 결과를 Save 했기 때문입니다. 이 과정에서 여러 트랜잭션이 동시에 같은 데이터를 읽고 수정하려 할 때 경쟁 조건이 발생했습니다.


<aside>

  1. 문제 해결 : 원자적 업데이트 </aside>
@Transactional
public PostResponseDto getPost(UUID postId) {
    Post post = postRepository.findByPostId(postId)
            .orElseThrow(() -> new GlowGlowException(GlowGlowError.POST_NO_EXIST));

    postRepository.incrementViews(postId);
    int updatedViews = postRepository.getViews(postId);
    post.setViews(updatedViews);

    return PostResponseDto.of(post);
}

@Modifying
@Query(value = "UPDATE p_posts SET views = views + 1 WHERE post_id = :postId", nativeQuery = true)
void incrementViews(@Param("postId") UUID postId);

@Query(value = "SELECT views FROM p_posts WHERE post_id = :postId", nativeQuery = true)
int getViews(@Param("postId") UUID postId);