λ‚˜μ˜ λͺ¨μ–‘

052 | Transaction λ³Έλ¬Έ

SEB/TIL

052 | Transaction

kexon 2022. 9. 5. 22:27

πŸŽˆνŠΈλžœμž­μ…˜μ΄λž€?

  • μ—¬λŸ¬κ°œμ˜ μž‘μ—…λ“€μ„ ν•˜λ‚˜λ‘œ λ¬Άμ–΄μ„œ μ²˜λ¦¬ν•˜λŠ” 처리 λ‹¨μœ„μ΄λ‹€.
  • λ°μ΄ν„°μ˜ 무결성을 보μž₯ν•˜λŠ” 핡심적인 역할을 ν•œλ‹€.

🧩 ACID 원칙

  • μ›μžμ„±(Atomicity)
    • ν•˜λ‚˜μ˜ 논리적 κΈ°λŠ₯을 μˆ˜ν–‰ν•˜κΈ° μœ„ν•œ μž‘μ—…μ˜ κΈ°λ³Έ λ‹¨μœ„μ΄λ‹€.
    • μƒνƒœ λ³€ν™”λŠ” All or Nothing λ‘˜ 쀑 ν•˜λ‚˜둜 μ²˜λ¦¬λ˜μ–΄μ•Ό ν•œλ‹€.
  • 일관성(Consistency)
    • νŠΈλžœμž­μ…˜ 성곡 ν›„ μΌκ΄€λœ DB μƒνƒœλ₯Ό 보쑴해야 ν•œλ‹€.
  • 고립성(Isolation)
    • μ—¬λŸ¬ 개의 νŠΈλžœμž­μ…˜μ΄ 싀행될 경우 각각 λ…λ¦½μ μœΌλ‘œ 싀행이 λ˜μ–΄μ•Ό ν•œλ‹€.
  • 지속성(Durability)
    • νŠΈλžœμž­μ…˜ 성곡 ν›„ κ²°κ³ΌλŠ” μ§€μ†μ μœΌλ‘œ DB에 μ €μž₯λ˜μ–΄μ•Ό ν•œλ‹€.

🧩 컀밋(commit)

  • λͺ¨λ“  μž‘μ—…μ„ DB에 μ΅œμ’… λ°˜μ˜ν•˜λŠ” λͺ…령어이닀.
  • commit을 ν•˜λ©΄ λ³€κ²½λœ λ‚΄μš©μ΄ λ°μ΄ν„°λ² μ΄μŠ€μ— 영ꡬ적으둜 μ €μž₯된 ν›„ μ’…λ£Œλœλ‹€.
  • commit을 ν•˜μ§€ μ•ŠμœΌλ©΄ μž‘μ—…μ˜ κ²°κ³Όκ°€ λ°μ΄ν„°λ² μ΄μŠ€μ— μ΅œμ’…μ μœΌλ‘œ λ°˜μ˜λ˜μ§€ μ•Šκ³  μ’…λ£Œλœλ‹€.

🧩 둀백(rollback)

  • μž‘μ—… 쀑 λ¬Έμ œκ°€ λ°œμƒλ˜λ©΄ μˆ˜ν–‰λœ μž‘μ—…λ“€μ„ μ·¨μ†Œν•˜κ³  νŠΈλžœμž­μ…˜ μ‹œμž‘ 이전 μƒνƒœλ‘œ λ˜λŒμ•„κ°„λ‹€.
@Configuration
public class Entity {
    private EntityManager
    private EntityTransaction tx;

    @Bean
    public CommandLineRunner jpaRunner(EntityManagerFactory emFactory){
        this.em = emFactory.createEntityManager();
        this.tx = em.getTransaction();

        return args -> {
            tx.begin();
			// transaction
            tx.commit();
        };
    }
}

🎈Annotation Transaction

  • Springμ—μ„œ κ°€μž₯ κ°„λ‹¨ν•˜κ²Œ νŠΈλžœμž­μ…˜μ„ μ μš©ν•  수 μžˆλŠ” λ°©λ²•μœΌλ‘œ, @Transactional을 μ‚¬μš©ν•œλ‹€.
@Service
@Transactional
public class Service {
	// ...
}
  • JPA 둜그 레벨 μ„€μ •
    • application.yml에 섀정을 μΆ”κ°€ν•˜λ©΄ νŠΈλžœμž­μ…˜ 둜그λ₯Ό 확인할 수 μžˆλ‹€.
    • 둜그 λ ˆλ²¨μ„ ‘DEBUG’ 레벨둜 μ„€μ •ν•˜λ©΄ JPA λ‚΄λΆ€μ—μ„œ μ§€μ •ν•œ λΆ€λΆ„μ˜ 둜그λ₯Ό 확인할 수 μžˆλ‹€.
    • loggingνƒœκ·ΈλŠ” μ΅œμƒμœ„ λ ˆλ²¨μ΄λ―€λ‘œ νƒ­ 없이 μ™Όμͺ½μ— λΆ™μ—¬μ„œ 써야 ν•œλ‹€.
logging:
  level:
    org:
      springframework:
        orm:
          jpa: DEBUG

🧩 클래슀 레벨

  • νŠΈλžœμž­μ…˜ 적용 확인
    • Creating new transaction: μƒˆλ‘œμš΄ νŠΈλžœμž­μ…˜ 생성
    • Committing JPA transaction on EntityManager: 컀밋 싀행쀑
    • after transaction: νŠΈλžœμž­μ…˜ μ’…λ£Œ
    • Closing JPA EntityManager: JPA EntityManager μ’…λ£Œμ€‘
  • μ˜ˆμ™Έ λ˜μ§€κΈ° - RuntimeException

  • check exception
    • @Transactional μ• λ„ˆν…Œμ΄μ…˜λ§Œ μΆ”κ°€ν•΄μ„œλŠ” rollback이 λ˜μ§€ μ•ŠλŠ”λ‹€.
    • λ³„λ„μ˜ μ˜ˆμ™Έ 처리λ₯Ό ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€λ©΄ @Transactional(rollbackFor = {Exception1.class, Exception2.class, ...})와 같이 ν•΄λ‹Ή 체크 μ˜ˆμ™Έλ₯Ό 직접 μ§€μ •ν•΄μ£Όκ±°λ‚˜ 언체크 μ˜ˆμ™Έ(unchecked exception)λ₯Ό ν™œμš©ν•΄ rollback이 λ™μž‘ν•˜λ„λ‘ ν•  수 μžˆλ‹€.

🧩 λ©”μ„œλ“œ λ ˆλ²¨

@Transactional(readOnly = true)
public Entity findEntity(long Id) {

    return findVerifiedEntity(Id);
}
  • @Transactional(readOnly = true)λŠ” νŠΈλžœμž­μ…˜μ„ 읽기 μ „μš©μœΌλ‘œ μ‹€ν–‰ν•œλ‹€. JPA λ‚΄λΆ€μ μœΌλ‘œ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈλ₯Ό flushν•˜μ§€ μ•ŠλŠ”λ‹€. 또 읽기 μ „μš© νŠΈλžœμž­μ…˜μΌ 경우, λ³€κ²½ 감지λ₯Ό μœ„ν•œ μŠ€λƒ…μƒ· 생성도 μ§„ν–‰ν•˜μ§€ μ•ŠλŠ”λ‹€.
  • 읽기 μ „μš© νŠΈλžœμž­μ…˜μΌ λ•ŒλŠ” 변경감지λ₯Ό ν•˜μ§€ μ•Šμ•„ λΆˆν•„μš”ν•œ μΆ”κ°€ λ™μž‘μ„ 쀄일 수 있기 λ•Œλ¬Έμ— find~() λ©”μ„œλ“œμ—λŠ” JPA 자체적으둜 μ„±λŠ₯을 μ΅œμ ν™”ν•˜κΈ° λ•Œλ¬Έμ— readOnlyλ₯Ό true둜 μ§€μ •ν•˜λŠ”κ²ƒμ΄ μ’‹λ‹€.

🧩 νŠΈλžœμž­μ…˜ 적용 μˆœμ„œ

  • μš°μ„ μˆœμœ„ : 클래슀레벨 < λ©”μ„œλ“œλ ˆλ²¨

🧩 νŠΈλžœμž­μ…˜ μ „νŒŒ(Transaction Propagation)

  • νŠΈλžœμž­μ…˜μ˜ κ²½κ³„μ—μ„œ 진행 쀑인 νŠΈλžœμž­μ…˜μ΄ μ‘΄μž¬ν•˜κ±°λ‚˜ μ‘΄μž¬ν•˜μ§€ μ•Šμ„ λ•Œ, μ–΄λ–»κ²Œ λ™μž‘ν•  것인지 κ²°μ •ν•˜λŠ” 방식이닀. νŠΈλžœμž­μ…˜μ΄ ν•˜λ‚˜λ§Œ μžˆλ‹€λ©΄ λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ„ μ‹ κ²½ μ“Έ ν•„μš”κ°€ μ—†μ§€λ§Œ νŠΈλžœμž­μ…˜μ΄ n개 이상 더 μžˆμ„ 수 μžˆλ‹€λ©΄ κ²½κ³„μ—μ„œ 상황에 따라 λ‹€λ₯΄κ²Œ λŒ€μ²˜ν•΄μ•Ό ν•œλ‹€.
  • νŠΈλžœμž­μ…˜ μ „νŒŒλŠ” propagation Attributeλ₯Ό ν†΅ν•΄μ„œ μ„€μ •ν•  수 μžˆλ‹€.
    • Propagation.REQUIRED (default): 진행 쀑인 νŠΈλžœμž­μ…˜μ΄ 있으면 ν•΄λ‹Ή νŠΈλžœμž­μ…˜μ— μ°Έμ—¬ν•˜κ³  진행 쀑인 νŠΈλžœμž­μ…˜μ΄ μ—†μœΌλ©΄ μƒˆλ‘œ μƒμ„±ν•œλ‹€.
    • Propagation.REQUIRES_NEW: 이미 진행쀑인 νŠΈλžœμž­μ…˜κ³Ό λ¬΄κ΄€ν•˜κ²Œ μƒˆλ‘œμš΄ νŠΈλžœμž­μ…˜μ΄ μ‹œμž‘λœλ‹€. 기쑴에 μ§„ν–‰μ€‘μ΄λ˜ νŠΈλžœμž­μ…˜μ€ μƒˆλ‘œ μ‹œμž‘λœ νŠΈλžœμž­μ…˜μ΄ μ’…λ£Œν•  λ•ŒκΉŒμ§€ μ€‘μ§€λœλ‹€.
    • Propagation.MANDATORY: 진행 쀑인 νŠΈλžœμž­μ…˜μ΄ μ—†μœΌλ©΄ μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚¨λ‹€.
    • Propagation.NOT_SUPPORTED: 진행 쀑인 νŠΈλžœμž­μ…˜μ΄ 있으면 λ©”μ„œλ“œ 싀행이 μ’…λ£Œλ  λ•Œ κΉŒμ§€ μ€‘μ§€λ˜κ³ , λ©”μ„œλ“œ 싀행이 μ’…λ£Œλ˜λ©΄ 계속 μ§„ν–‰ν•œλ‹€.
    • Propagation.NEVER: νŠΈλžœμž­μ…˜μ„ μ‚¬μš©ν•˜μ§€ μ•Šκ³ , 진행 쀑인 νŠΈλžœμž­μ…˜μ΄ μ‘΄μž¬ν•  κ²½μš°μ—λŠ” μ˜ˆμ™Έλ₯Ό λ°œμƒν‚¨λ‹€.

🧩 νŠΈλžœμž­μ…˜ 격리 μˆ˜μ€€(Isolation Level)

  • νŠΈλžœμž­μ…˜μ€ λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ— 영ν–₯을 주지 μ•Šκ³  격리성(λ…λ¦½μ μœΌλ‘œ μ‹€ν–‰)이 보μž₯λ˜μ–΄μ•Ό ν•œλ‹€. κ·Έλž˜μ„œ Spring은 μ—¬λŸ¬ νŠΈλžœμž­μ…˜μ΄ λ™μ‹œμ— 싀행될 λ•Œ 격리성을 μ‘°μ •ν•  수 있게 @Transactionalμ—μ„œ isolation Attributeλ₯Ό μ œκ³΅ν•˜κ³  μžˆλ‹€.
    • Isolation.DEFAULT (default): λ°μ΄ν„°λ² μ΄μŠ€μ—μ„œ μ œκ³΅ν•˜λŠ” κΈ°λ³Έ 값이닀.
    • Isolation.READ_UNCOMMITTED: λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ—μ„œ μ»€λ°‹ν•˜μ§€ μ•Šμ€ 데이터λ₯Ό μ½λŠ” 것을 ν—ˆμš©ν•œλ‹€.
    • Isolation.READ_COMMITTED: λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ— μ˜ν•΄ μ»€λ°‹λœ 데이터λ₯Ό μ½λŠ” 것을 ν—ˆμš©ν•œλ‹€.
    • Isolation.REPEATABLE_READ: λžœμž­μ…˜ λ‚΄μ—μ„œ ν•œ 번 μ‘°νšŒν•œ 데이터λ₯Ό λ°˜λ³΅ν•΄μ„œ μ‘°νšŒν•΄λ„ 같은 데이터가 μ‘°νšŒλ˜λ„λ‘ ν•œλ‹€.
    • Isolation.SERIALIZABLE: λ™μΌν•œ 데이터에 λŒ€ν•΄μ„œ λ™μ‹œμ— 두 개 μ΄μƒμ˜ νŠΈλžœμž­μ…˜μ΄ μˆ˜ν–‰λ˜μ§€ λͺ»ν•˜λ„둝 ν•œλ‹€.

🎈AOP Transaction

  • @Transactional을 λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ— μ μš©ν•˜μ§€ μ•Šκ³  νŠΈλžœμž­μ…˜μ„ μ μš©ν•˜λŠ” 방법이닀.
  • AOP ꡬ성
    • Advisor: Advice와 pointcut ν¬ν•¨ν•˜κ³  μžˆλ‹€.
    • Pointcut: λΉ„μ¦ˆλ‹ˆμŠ€ 둜직의 정보λ₯Ό 가지고 μžˆλ‹€.
    • Advice: pointcutμ—μ„œ 싀행될 곡톡관심사이닀.

'SEB > TIL' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

058 | Asciidocs, Asciidoctor  (2) 2022.09.15
057 | API Documentation, Swagger, SpringRest  (0) 2022.09.14
046 | Spring Data JDBC  (0) 2022.08.26
045 | Checked / Unchecked / Customised Exception  (0) 2022.08.25
044 | Exception Handling in Spring MVC  (0) 2022.08.24
Comments