νΈλμμ
(Transaction)μ΄λ λ°μ΄ν°λ² μ΄μ€μμ μ€νλλ νλμ λ
Όλ¦¬μ μΈ μμ
λ¨μλ₯Ό μλ―Ένλ€.
μ¦, μ¬λ¬ κ°μ SQL μ°μ°μ΄ νλμ νΈλμμ
μΌλ‘ λ¬Άμ¬ μ€νλλ©°,
λͺ¨λ μμ
μ΄ μ±κ³΅ν΄μΌ μ΅μ’
μ μΌλ‘ 컀λ°(commit)λκ³ ,
νλλΌλ μ€ν¨νλ©΄ λ‘€λ°±(rollback)λμ΄ μλ μνλ‘ λ³΅κ΅¬λλ€.
νΈλμμ μ΄ μ¬λ°λ₯΄κ² λμνλ €λ©΄ ACID μμΉμ λ§μ‘±ν΄μΌ νλ€.
νΉμ± | μ€λͺ |
---|---|
Atomicity (μμμ±) | νΈλμμ μ λͺ¨λ μ±κ³΅νκ±°λ, λͺ¨λ μ€ν¨ν΄μΌ ν¨ |
Consistency (μΌκ΄μ±) | νΈλμμ μ΄ μ€νλ ν λ°μ΄ν°λ² μ΄μ€κ° μΌκ΄λ μνλ₯Ό μ μ§ν΄μΌ ν¨ |
Isolation (격리μ±) | μ¬λ¬ νΈλμμ μ΄ λμμ μ€νλ λ μλ‘ μν₯μ μ£Όμ§ μμμΌ ν¨ |
Durability (μ§μμ±) | νΈλμμ μ΄ μ±κ³΅μ μΌλ‘ μλ£λλ©΄ λ°μ΄ν°κ° μꡬμ μΌλ‘ λ°μλμ΄μΌ ν¨ |
commit
μ΄ μνλ¨.INSERT
, UPDATE
, DELETE
μ€ν μ μλμΌλ‘ λ³κ²½μ¬νμ΄ μ μ₯λ¨.// κΈ°λ³Έμ μΌλ‘ Auto Commit λͺ¨λκ° νμ±νλ¨
Connection conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
stmt.executeUpdate("INSERT INTO users (name, age) VALUES ('Alice', 25)");
// μλμΌλ‘ commit() μνλ¨
setAutoCommit(false)
λ₯Ό μ¬μ©νμ¬ μλ 컀λ°μ λΉνμ±ννκ³ ,commit()
λλ rollback()
μ μ§μ νΈμΆνμ¬ νΈλμμ
μ κ΄λ¦¬νλ€.Connection conn = DriverManager.getConnection(url, user, password);
conn.setAutoCommit(false); // μλ μ»€λ° λΉνμ±ν
try {
PreparedStatement pstmt1 = conn.prepareStatement("UPDATE accounts SET balance = balance - 1000 WHERE id = 1");
pstmt1.executeUpdate();
PreparedStatement pstmt2 = conn.prepareStatement("UPDATE accounts SET balance = balance + 1000 WHERE id = 2");
pstmt2.executeUpdate();
conn.commit(); // λͺ¨λ μμ
μ΄ μ±κ³΅νλ©΄ commit μν
} catch (SQLException e) {
conn.rollback(); // μ€λ₯ λ°μ μ rollback μν
} finally {
conn.setAutoCommit(true); // νΈλμμ
μ’
λ£ ν Auto Commit μμ 볡ꡬ
}
π νΈλμμ μ΄ μ μ©λμ§ μμΌλ©΄ 첫 λ²μ§Έ SQLμ΄ μ€νλ ν μ€λ₯κ° λ°μνλ©΄, A κ³μ’μμλ μΆκΈλμμ§λ§, B κ³μ’μλ μ κΈλμ§ μλ λ¬Έμ λ°μ
π νΈλμμ μ μ μ©νλ©΄ νλλΌλ μ€ν¨νλ©΄ λͺ¨λ μμ μ΄ λ‘€λ°±(rollback) λμ΄ λ°μ΄ν° μ ν©μ±μ μ μ§ κ°λ₯
νΈλμμ
격리 μμ€(Isolation Level)μ
λμμ μ¬λ¬ νΈλμμ
μ΄ μ€νλ λ, λ€λ₯Έ νΈλμμ
μ λ³κ²½μ¬νμ μΌλ§λ νμ©ν μ§λ₯Ό κ²°μ νλ€.
격리 μμ€ | μ€λͺ | λ°μν μ μλ λ¬Έμ |
---|---|---|
READ UNCOMMITTED | λ€λ₯Έ νΈλμμ
μ΄ commit λμ§ μμ λ°μ΄ν°λ μ½μ μ μμ | Dirty Read λ°μ κ°λ₯ |
READ COMMITTED | λ€λ₯Έ νΈλμμ
μ΄ commit ν λ°μ΄ν°λ§ μ½μ μ μμ | Non-repeatable Read λ°μ κ°λ₯ |
REPEATABLE READ | κ°μ νΈλμμ μμ κ°μ λ°μ΄ν°λ₯Ό μ¬λ¬ λ² μ½μ΄λ κ°μ΄ λ³νμ§ μμ | Phantom Read λ°μ κ°λ₯ |
SERIALIZABLE | λͺ¨λ νΈλμμ μ μμ°¨μ μΌλ‘ μ€ν | μ±λ₯ μ ν κ°λ₯ |
// νΈλμμ
격리 μμ€ μ€μ
conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
import java.sql.*;
public class TransactionExample {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/testdb";
String user = "root";
String password = "1234";
Connection conn = null;
try {
conn = DriverManager.getConnection(url, user, password);
conn.setAutoCommit(false); // μλ μ»€λ° λΉνμ±ν
// 첫 λ²μ§Έ SQL μ€ν (A κ³μ’μμ 1000μ μΆκΈ)
PreparedStatement pstmt1 = conn.prepareStatement("UPDATE accounts SET balance = balance - 1000 WHERE id = 1");
pstmt1.executeUpdate();
// λ λ²μ§Έ SQL μ€ν (B κ³μ’μ 1000μ μ
κΈ)
PreparedStatement pstmt2 = conn.prepareStatement("UPDATE accounts SET balance = balance + 1000 WHERE id = 2");
pstmt2.executeUpdate();
conn.commit(); // μ±κ³΅νλ©΄ 컀λ°
System.out.println("β
νΈλμμ
μ±κ³΅: A β B κ³μ’ μ΄μ²΄ μλ£");
} catch (SQLException e) {
try {
if (conn != null) conn.rollback(); // μ€λ₯ λ°μ μ λ‘€λ°±
System.out.println("β μ€λ₯ λ°μ: νΈλμμ
λ‘€λ°± μν");
} catch (SQLException rollbackEx) {
rollbackEx.printStackTrace();
}
e.printStackTrace();
} finally {
try { if (conn != null) conn.close(); } catch (SQLException e) { e.printStackTrace(); }
}
}
}
β
νΈλμμ
(Transaction)μ μ¬λ¬ κ°μ SQL μμ
μ νλμ μμ
λ¨μλ‘ λ¬Άμ΄μ μ€ννλ κΈ°λ₯
β
νΈλμμ
μ΄ μ μ©λλ©΄ commit()
μ νΈμΆν΄μΌ λ³κ²½ μ¬νμ΄ λ°μλλ©°, rollback()
μΌλ‘ μ·¨μ κ°λ₯
β
JDBCμμ setAutoCommit(false)
, commit()
, rollback()
μ νμ©νμ¬ νΈλμμ
μ μ μ© κ°λ₯
β
XA νΈλμμ
μ νμ©νλ©΄ μ¬λ¬ κ°μ λ°μ΄ν°λ² μ΄μ€μμ μ€νλλ SQLμ νλμ νΈλμμ
μΌλ‘ λ¬Άμ μ μμ