νΈλμμ μ νμ κ΄νμ¬
by rlaehddnd0422νΈλμμ μ νλ?
'ν νΈλμμ λ΄μμ λ€λ₯Έ νΈλμμ μ νΈμΆν λ μ΄λ»κ² μ²λ¦¬νλ κ°?'μ λν κ°λ μ λλ€.
κ°κ°μ νΈλμμ μ΄ λ³κ°λ‘ μνλλ κ²½μ°
μ°μ λ νΈλμμ μ΄ κ°κ° λ°λ‘ μ¬μ©λλ κ²½μ°λ₯Ό νμΈν΄λ΄ μλ€.
@Test
void double_commit()
{
log.info("νΈλμμ
1 μμ");
TransactionStatus status1 = transactionManager.getTransaction(new DefaultTransactionAttribute());
log.info("νΈλμμ
1 μ»€λ° μμ");
transactionManager.commit(status1);
log.info("νΈλμμ
2 μμ");
TransactionStatus status2 = transactionManager.getTransaction(new DefaultTransactionAttribute());
log.info("νΈλμμ
2 μ»€λ° μμ");
transactionManager.commit(status2);
}
νΈλμμ μ μμν λλ @Transactionalμ μ¬μ©νλκ² ν΅μμ μ΄κΈ΄ ν©λλ€λ§ νΈλμμ 맀λμ μμ 컀λ₯μ μ μ»μ΄ νΈλμμ μ λμκ³Όμ μ μ€λͺ νκΈ° μν΄ νΈλμμ 맀λμ λ₯Ό μ§μ μ¬μ©ν΄ νΈλμμ μ μννμ΅λλ€.
νΈλμμ 1μ΄ μμλκ³ μ»€λ°λ μ΄ν νΈλμμ 2κ° νΈμΆλμκΈ° λλ¬Έμ, λμκ³Όμ μ μ΄λ μ΅λλ€.
- getTransaction()μΌλ‘ νΈλμμ
μμ
- νΈλμμ 맀λμ κ° DataSourceλ₯Ό κΈ°λ°μΌλ‘ 컀λ₯μ μ μμ±ν΄μ νΈλμμ λκΈ°ν 맀λμ μ 보κ΄
- λ‘μ§ μν by 1-1μμ 보κ΄λ 컀λ₯μ μ κΈ°λ°μΌλ‘ SQL μν (μλ΅)
- commit() / rollback()
μ΄λ κ² κ°κ° μνλλ κ²½μ° μ»€λ₯μ μ΄ λ€λ₯΄κΈ° λλ¬Έμ νΈλμμ 1κ³Ό νΈλμμ 2λ λ³κ°μ νΈλμμ μΌλ‘ μνλ©λλ€.
μ¦, νΈλμμ 1κ³Ό νΈλμμ 2λ μλ‘ μνΈ λ 립μ μΌλ‘ μνλκΈ° λλ¬Έμ κ°κ°μ 컀λ°/λ‘€λ°±μ κ²°κ³Όκ° μλ‘μκ² μν₯μ μ£Όμ§μμ΅λλ€.
κ·Έλ λ€λ©΄ νΈλμμ 1μμ νΈλμμ 2λ₯Ό νΈμΆνλ κ²½μ°λ μ΄λ¨κΉμ?
νΈλμμ μ§νμ€μ μλ‘μ΄ νΈλμμ μ νΈμΆνλ κ²½μ° : νΈλμμ μ ν
νλμ νΈλμμ μ§νμ€μ μλ‘μ΄ νΈλμμ μ νΈμΆνλ κ²μ νΈλμμ μ νλΌκ³ ν©λλ€.
νλμ νΈλμμ μ§νμ€μ μλ‘μ΄ νΈλμμ μ νΈμΆνκ² λλ©΄ μ΄λ»κ² λμν κΉμ?
1. λ νΈλμ°μ μ νλμ 물리 νΈλμμ μΌλ‘ λ¬Άμ΄κ² λ©λλ€.
2. νλμ 물리 νΈλμμ λ΄μ κ°κ°μ νΈλμμ μ λ Όλ¦¬ νΈλμμ μΌλ‘ ꡬλΆν©λλ€.
μ΄ λ μ€μν μμΉμ΄ μμ΅λλ€.
1. λͺ¨λ λ Όλ¦¬ νΈλμμ μ΄ μ»€λ°λμ΄μΌ 물리 νΈλμμ μ΄ μ»€λ°λ©λλ€.
2. νλμ λ Όλ¦¬νΈλμμ μ΄λΌλ λ‘€λ°±λλ κ²½μ° λ¬Όλ¦¬ νΈλμμ μ λ‘€λ°±λ©λλ€.
νΈλμμ 2λ νΈλμμ 1μ μν΄μ νΈμΆλ νΈλμμ μ΄λ―λ‘ μ κ· νΈλμμ μΌλ‘ μμλμ§ μκ³ , κΈ°μ‘΄ νΈλμμ μΈ νΈλμμ 1μ participate νμ¬ λμν©λλ€.
Q. μ κ· νΈλμμ μΈμ§ μ°Έμ¬ νΈλμμ μΈμ§ λ΄λΆμμ μ΄λ»κ² νμ ν κΉ?
A. λ΄λΆμ μΌλ‘ νΈλμμ λκΈ°ν 맀λμ λ₯Ό ν΅ν΄ κΈ°μ‘΄ νΈλμμ μ΄ μ‘΄μ¬νλμ§ νμΈνκ³ , κΈ°μ‘΄ νΈλμμ μ΄ μμΌλ©΄ κ°μ 컀λ₯μ μ μ¬μ©νλλ‘ μ€μ λμ΄μμ΅λλ€.
νΈλμμ 맀λμ λ νΈλμμ μ μμ±ν κ²°κ³Όλ₯Ό TransactionStatusμ λ΄μμ 리ν΄νλλ°, μ¬κΈ°μ isNewTransactionμ ν΅ν΄ μ κ· νΈλμμ μ¬λΆλ₯Ό νμΈν μ μμ΅λλ€.
μ°Έμ¬ νΈλμμ μ μ΄λ€ μλ―Έλ₯Ό κ°μ§κΉμ?
μ°Έμ¬ νΈλμμ μ λ§ κ·Έλλ‘ κΈ°μ‘΄ νΈλμμ μ "μ°Έμ¬"νλ νΈλμμ μ λλ€. λ°λΌμ μ°Έμ¬ νΈλμμ μ΄ μ»€λ°λμ΄λ, μ κ· νΈλμμ μ΄ μ»€λ°λμ§ μμΌλ©΄ λ‘€λ°±λκΈ° λλ¬Έμ μ°Έμ¬ νΈλμμ μ 컀λ°νλ μμ μ μ€μ λ‘ λ Όλ¦¬μ νΈλμμ μ΄λ 물리μ νΈλμμ μ 컀λ°νμ§ μμ΅λλ€. μ‘°κΈ λ μ½κ² λ§νλ©΄, μ°Έμ¬ νΈλμμ μ commit()μ κ±Έμ΄μ£Όμ΄λ μ€μ λ‘λ μλ¬΄λ° λμμ νμ§ μμ΅λλ€.
Q. μ°Έμ¬ νΈλμμ μ΄ rollback()μ μνν΄λ μλ¬΄λ° λμμ νμ§ μλμ?
A. κ·Έλ μ§ μμ΅λλ€. λ€μμ μ°Έμ¬(λ΄λΆ) νΈλμμ μ λ‘€λ°± μ λμκ³Όμ μ μ΄ν΄λ³΄κ² μ§λ§, μ°Έμ¬ νΈλμμ μμ rollbackμ μννλ©΄ μ κ· νΈλμμ μκ² rollbackOnly μ΅μ μ μ λ¬ν΄ μ€μΌλ‘μ¨ λ¬Όλ¦¬ νΈλμμ μ΄ rollback λκ²λ λμνλλ‘ μ λν©λλ€.
νΈλμμ μ ν - μΈλΆ λ‘€λ°±
μμ² flow
1. νΈλμμ 1 νΈμΆ
- νΈλμμ 1μμλ νΈλμμ 맀λμ λ₯Ό getTransaction()μΌλ‘ νΈμΆνμ¬ νΈλμμ μ μμν©λλ€.
- νΈλμμ 맀λμ λ κΈ°μ‘΄ νΈλμμ μ΄ μ‘΄μ¬νλμ§ νμΈν©λλ€.
- μ‘΄μ¬νμ§ μμΌλ―λ‘ DataSourceλ₯Ό ν΅ν΄ 컀λ₯μ μ μμ±ν΄ λκΈ°ν 맀λμ μ 보κ΄ν©λλ€.
- 컀λ₯μ μ κΈ°λ°μΌλ‘ λ‘μ§μμ SQL μν
2. νΈλμμ 1μμ νΈλμμ 2 νΈμΆ
- νΈλμμ 2 λν νΈλμμ 맀λμ λ₯Ό getTransaction()μΌλ‘ νΈμΆνμ¬ νΈλμμ μ μμν©λλ€.
- νΈλμμ 맀λμ λ κΈ°μ‘΄ νΈλμμ μ΄ μ‘΄μ¬νλμ§ νμΈν©λλ€.
- κΈ°μ‘΄ νΈλμμ μ΄ μ‘΄μ¬νλ―λ‘ μ»€λ₯μ μ μ¬μ©νμ¬ λ‘μ§μμ SQLμ μνν©λλ€.
μλ΅ flow
1. νΈλμμ 2 μ»€λ° (μ€μ 컀λ°λμ μν X)
- μ κ· νΈλμμ μ΄ μλ μ°Έμ¬ νΈλμμ μ΄κΈ° λλ¬Έμ 컀λ°μ νΈμΆν΄λ μνλμ§ μμ΅λλ€.
2. νΈλμμ 1 λ‘€λ°±
- μ κ· νΈλμμ μ΄κΈ° λλ¬Έμ 물리 νΈλμμ μ rollback()ν©λλ€.
Test Code
@Test
void outer_rollback()
{
log.info("μΈλΆ νΈλμμ
μμ");
TransactionStatus outer = transactionManager.getTransaction(new DefaultTransactionAttribute());
log.info("outer.isNewTransaction() = {}", outer.isNewTransaction());
innerCommit();
log.info("μΈλΆ νΈλμμ
λ‘€λ°±");
transactionManager.rollback(outer);
}
private void innerCommit() {
log.info("λ΄λΆ νΈλμμ
μμ");
TransactionStatus inner = transactionManager.getTransaction(new DefaultTransactionAttribute());
log.info("λ΄λΆ νΈλμμ
컀λ°");
transactionManager.commit(inner);
}
- innerCommit()μμ commit()μ νΈμΆν΄λ μ€μ 컀λ°μ΄ μ΄λ£¨μ΄μ§μ§ μλ κ²μ νμΈν μ μμ΅λλ€.
- λ΄λΆ νΈλμμ μ΄ μμλκ³ νΈλμμ 맀λμ λ₯Ό ν΅ν΄ μ κ· νΈλμμ μΈμ§ νμΈνκ³ , μ κ· νΈλμμ μ΄ μλλ―λ‘ κΈ°μ‘΄ νΈλμμ μ Participatingνλ κ²μ νμΈν μ μμ΅λλ€.
- μΈλΆ νΈλμμ μ΄ λ‘€λ°±λμ΄ μ 체 물리 νΈλμμ μ΄ λ‘€λ°±λλ κ²μ νμΈν μ μμ΅λλ€.
νΈλμμ μ ν - λ΄λΆ λ‘€λ°±
κ·Έλ λ€λ©΄ μ€μ νΈλμμ μ΄ μλ μ°Έμ¬ νΈλμμ μμ λ‘€λ°±μ΄ μΌμ΄λλ©΄ μ΄λ»κ² λ κΉμ?
μμ² νλ¦μ λμΌνκΈ° λλ¬Έμ μλ΅νκ³ , μλ΅νλ¦λ§ μ΄ν΄λ³΄κ² μ΅λλ€.
μλ΅ Flow
1. νΈλμμ 2(λ΄λΆ νΈλμμ ) μμ rollback νΈμΆ
- λ§μ°¬κ°μ§λ‘ μ κ· νΈλμμ μ΄ μλκΈ° λλ¬Έμ μ€μ rollbackμ νΈμΆνμ§ μμ΅λλ€.
- λμ νΈλμμ 맀λμ μ rollbackOnlyμ΅μ μ trueλ‘ μ€μ ν©λλ€.
2. νΈλμμ 1(μΈλΆ νΈλμμ )μμ commit νΈμΆ
- μ κ· νΈλμμ μ΄ λ§μ§λ§ νΈλμμ 맀λμ μ rollbackOnly μ΅μ μ΄ trueλ‘ μ€μ λμ΄ μμ΄ commitνμ§ μκ³ λ¬Όλ¦¬ νΈλμμ μ λ‘€λ°±ν©λλ€
- μ΄ λ νΈλμμ 맀λμ λ μΈλΆ νΈλμμ μ½λμ UnexpectedRollbackException μμΈλ₯Ό λμ§λλ€.
TestCode
@Test
void inner_rollback()
{
log.info("μΈλΆ νΈλμμ
μμ");
TransactionStatus outer = transactionManager.getTransaction(new DefaultTransactionAttribute());
log.info("outer.isNewTransaction() = {}", outer.isNewTransaction());
innerRollback();
log.info("μΈλΆ νΈλμμ
컀λ°");
assertThatThrownBy(() -> transactionManager.commit(outer))
.isInstanceOf(UnexpectedRollbackException.class);
}
λ΄λΆ νΈλμμ μ΄ λ‘€λ°±μ νΈμΆ βΆοΈ marking existing transaction as rollback-only(κΈ°μ‘΄ νΈλμμ μ rollbackOnly λ§νΉ)
λ‘€λ°± μ μ© νμ(rollbackOnly)κ° μμΌλ©΄ μΈλΆ νΈλμμ μ commitν΄λ 물리 νΈλμμ μ 컀λ°νλ κ²μ΄ μλλΌ λ‘€λ°±ν©λλ€.
μΈλΆ νΈλμμ κ³Ό λ΄λΆ νΈλμμ λΆλ¦¬νκΈ° - REQUIRES_NEW μ΅μ
Q. μΈλΆ νΈλμμ μ΄ λ΄λΆ νΈλμμ μ νΈμΆν λ, μ κ· νΈλμμ μ μμνκ² νλ λ°©λ²μ μμκΉμ?
A. λ΄λΆ νΈλμμ μ propagation μ΅μ μ REQUIRED_NEWμΌλ‘ μ€μ ν΄μ£Όλ©΄ μ κ· νΈλμμ μΌλ‘ μμν μ μμ΅λλ€.
μ΄ λ°©λ²μ λ΄λΆ νΈλμμ μ λ¬Έμ κ° μ겨λ μΈλΆ νΈλμμ μ μν₯μ μ£Όμ§ μμ΅λλ€.
λ°λλ‘ μΈλΆ νΈλμμ μ λ¬Έμ κ° μ겨λ λ΄λΆ νΈλμμ μ μν₯μ μ£Όμ§ μμ΅λλ€.
REQUIRES_NEW μ΅μ μ μ¬μ©νλ©΄ κΈ°μ‘΄ 컀λ₯μ μ μ¬μ©νλ κ²μ΄ μλλΌ, μλ‘μ΄ νΈλμμ μ μμνκΈ° λλ¬Έμ μΈλΆ νΈλμμ κ³Ό λ΄λΆ νΈλμμ μ λΆλ¦¬λκΈ° λλ¬Έμ, μν₯μ μλ‘ μ£Όμ§ μμ΅λλ€.
μ¦, μΈλΆ νΈλμμ κ³Ό λ΄λΆ νΈλμμ μ΄ κ°κ° λ³λμ 물리 νΈλμμ μ κ°μ§λλ€.
TestCode
@Test
void inner_rollback_REQUIRES_NEW()
{
log.info("μΈλΆ νΈλμμ
μμ");
TransactionStatus outer = transactionManager.getTransaction(new DefaultTransactionAttribute());
log.info("outer.isNewTransaction() = {}", outer.isNewTransaction());
innerRollback_requires_new();
log.info("μΈλΆ νΈλμμ
컀λ°");
transactionManager.commit(outer);
}
private void innerRollback_requires_new() {
log.info("λ΄λΆ νΈλμμ
μμ");
DefaultTransactionAttribute definition = new DefaultTransactionAttribute();
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
TransactionStatus inner = transactionManager.getTransaction(definition);
log.info("inner.isNewTransaction() = {}", inner.isNewTransaction());
log.info("λ΄λΆ νΈλμμ
λ‘€λ°±");
transactionManager.rollback(inner);
}
1. μΈλΆ νΈλμμ μμ
2. λ΄λΆ νΈλμμ μμ
3. λ΄λΆ νΈλμμ λ‘€λ°± - μ κ· νΈλμμ μ΄λ―λ‘ μ€μ rollback νΈμΆ
4. μΈλΆ νΈλμμ μ»€λ° - μ κ· νΈλμμ μ΄λ―λ‘ μ€μ commit νΈμΆ
μ΅μ’ μ μΌλ‘ μΈλΆ νΈλμμ μ 컀λ°, λ΄λΆ νΈλμμ μ λ‘€λ°±λ©λλ€.
<μ 리>
- νΈλμμ μ νλ ν νΈλμμ λ΄μμ λ€λ₯Έ νΈλμμ μ νΈμΆνλ κ²½μ°λ₯Ό λ§ν©λλ€.
- μ΄ λ μΈλΆ νΈλμμ κ³Ό λ΄λΆ νΈλμμ μ κ°κ° λ Όλ¦¬ νΈλμμ μ΄λΌ λΆλ₯΄κ³ , μ΄λ₯Ό λ¬Άμ΄ λ¬Όλ¦¬ νΈλμμ μ΄λΌ λΆλ¦ λλ€.
- λͺ¨λ λ Όλ¦¬ νΈλμμ μ΄ μ»€λ°λλ κ²½μ°μλ§ λ¬Όλ¦¬ νΈλμμ μ΄ μ»€λ°λ©λλ€.
- λ¨ νλμ λ Όλ¦¬ νΈλμμ μ΄λΌλ λ‘€λ°±λλ κ²½μ° λ¬Όλ¦¬ νΈλμμ μ΄ λ‘€λ°±λμ΄ λͺ¨λ λ Όλ¦¬ νΈλμμ μ λ‘€λ°±λ©λλ€.
- λ΄λΆ νΈλμμ μ μΈλΆ νΈλμμ μ μ°Έμ¬νλ λ Όλ¦¬ νΈλμμ μ΄κΈ° λλ¬Έμ, commitμ νΈμΆν΄λ μλ¬΄λ° λμμ νμ§ μμ΅λλ€.
- λ°λ©΄, λ΄λΆ νΈλμμ
μμ rollbackμ νΈμΆνλ κ²½μ° νΈλμμ
맀λμ μ rollbackOnly μ΅μ
μ trueλ‘ μ€μ νκΈ° λλ¬Έμ, μΈλΆ νΈλμμ
μ μ΄ μ΅μ
μ΄ trueλ‘ μ€μ λμ΄ μμΌλ©΄ μ κ· νΈλμμ
쑰건과 μκ΄μμ΄ μΈλΆ νΈλμμ
μ΄ commit λλλΌλ 물리 νΈλμμ
rollbackμ νΈμΆν©λλ€.
- rollbackOnly μ΅μ μ΄ trueλ‘ μ€μ λμ΄ λ¬Όλ¦¬ νΈλμμ μ΄ λ‘€λ°±λλ κ²½μ°, νΈλμμ 맀λμ λ UnexpectedRollbackException μμΈλ₯Ό νΈμΆ μ½λμκ² λ΄λμ§μΌλ‘μ¨, λͺ ννκ² λ¬Έμ λ₯Ό μλ €μ€λλ€.
<μ°Έκ³ μλ£>
'π Backend > DB Access' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
νΈλμμ AOP @Transactionalμ μ΅μ (0) | 2023.04.20 |
---|---|
νΈλμμ AOP @Transactional μ¬μ© μ μ£Όμμ¬ν (1) | 2023.04.20 |
[Querydsl] Querydsl μ΄λ? (0) | 2023.04.19 |
[Spring Data JPA] μ€νλ§ λ°μ΄ν° JPA (0) | 2023.04.17 |
[JPA] JPA(Java Persistent API) (0) | 2023.04.17 |
λΈλ‘κ·Έμ μ 보
Study Repository
rlaehddnd0422