트랜잭션 관리(commit, rollback)
트랜잭션은 여러 SQL 문을 하나의 작업 단위로 묶어주는 것을 의미한다. commit은 트랜잭션을 완료하여 변경사항을 저장하고, rollback은 트랜잭션을 취소하여 변경사항을 되돌린다.
트랜잭션의 개념과 중요성
트랜잭션의 개념
트랜잭션(Transaction)은 데이터베이스에서 하나의 논리적인 작업 단위를 의미한다. 여러 SQL 문이 하나의 작업으로 묶여서 실행된다.
트랜잭션은 원자성(Atomicity), 일관성(Consistency), 고립성(Isolation), 지속성(Durability)의 특성을 갖는다. 이를 ACID특성이라고 한다.
원자성(Atomicity) | 원자성은 트랜잭션의 모든 작업이 성공적으로 완료되거나 전혀 실행되지 않은 상태를 보장한다. 트랜잭션 내의 모든 작업이 성공하면 트랜잭션이 커밋되어 데이터베이스에 적용되고, 트랜잭션 중 하나라도 실패하면 트랜잭션이 롤백되어 모든 변경사항이 취소된다. (마치 은행에서 이체 작업을 할 때 돈이 출금되었지만 입금되지 않거나 입금되었지만 출금되지 않는 상황이 없어야 하는 것과 같다. 둘 다 성공하거나 둘 다 실패해야 한다.) |
일관성(Consistency) | 일관성은 트랜잭션이 실행되기 전과 후에 데이터베이스가 일관된 상태를 유지함을 보장한다. (은행에서 고객의 잔고가 음수가 되지 않도록 하는 규칙이 항상 지켜지는 것을 보장한다.) |
고립성(Isolation) | 동시에 실행되는 트랜잭션들이 서로 간섭하지 않도록 보장한다. 하나의 트랜잭션이 완료되기 전까지는 다른 트랜잭션이 그 트랜잭션의 중간 결과를 볼 수 없다. (여러 사용자가 동시에 은행 계좌를 업데이트 할 때 각 사용자가 자신의 작업이 완료되기 전까지 다른 사용자의 업데이트를 볼 수 없다.) 트랜잭션 두 개가 동시에 같은 데이터를 수정할 때 각각 고립되어 있어야 하며, 순서에 상관없이 같은 결과를 생성해야 한다. |
지속성(Durability) | 트랜잭션이 성공적으로 커밋된 후에는 시스템 장애가 발생하더라도 그 결과가 데이터베이스에 영구적으로 반영됨을 보장한다. (은행에서 이체가 완료된 후 시스템이 갑자기 중단되더라도 이체된 금액이 손실되지 않고 그대로 유지되는 것을 보장한다.) |
자동 커밋 모드와 수동 커밋 모드
자동 커밋 모드
기본적으로 JDBC는 자동 커밋 모드이다. 각 SQL문이 실행될 때마다 자동으로 커밋된다.
○ 설정 : connection.setAutoCommit(true);
수동 커밋 모드
수동 커밋 모드는 여러 SQL 문을 트랜잭션 하나로 묶어서 실행할 수 있다. 트랜잭션을 명시적으로 커밋하거나 롤백할 수 있다.
○ 설정 : connection.setAutoCommit(false);
○ 커밋 : connection.commit();
○ 롤백 : connection.rollback();
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class TransactionExample {
public static void main(String[] args) {
// 드라이버 -> MySQL 개발자들이 자바 코드로 작성한 클래스의 묶음(.jar)
// ver 8.0
String url = "jdbc:mysql://localhost:3306/m_board?serverTimezone=Asia/Seoul";
String id = "root";
String pw = "asd123";
// 구현체를 사용하기 위해서
// 클래스 Class <-- 최상위 Object 안에 있음.
// 동적 바인딩 처리
try {
// mysql 드라이버(구현클래스) 메모리에 로드
Class.forName("com.mysql.cj.jdbc.Driver");
// try catch resource 문법
try (Connection conn = DriverManager.getConnection(url, id, pw);) {
conn.setAutoCommit(false); // 수동 커밋 모드 설정
String sqlInsert = "INSERT INTO user(username, password, email, userRole, address, createDate) \r\n"
+ " values(?,?,?,?,?,now())";
PreparedStatement psmt = conn.prepareStatement(sqlInsert);
psmt.setString(1, "이름");
psmt.setString(2, "비밀번호");
psmt.setString(3, "이메일@구글");
psmt.setString(4, "유저롤");
psmt.setString(5, "주소");
psmt.executeUpdate();
String sqlUpdate = "UPDATE user SET email = ? WHERE username = ?";
PreparedStatement psmt2 = conn.prepareStatement(sqlUpdate);
psmt2.setString(1, "jj@naver.com");
psmt2.setString(2, "라라");
psmt2.executeUpdate();
// 수동 커밋 모드를 설정했다면 직접 commit() 실행해야
// 물리적인 저장장치에 영구히 반영이 된다.
conn.commit();
} catch (Exception e) {
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} // end of main
} // end of class
배치 처리(Batch Processing)
데이터를 일괄적으로 모아서 한 번에 처리하는 방법이다. 대량의 데이터를 처리하거나 주기적으로 실행되는 작업을 자동화하는데 사용한다. 일반적으로 대화형 사용자 입력없이 실행되며, 백그라운드에서 작업이 수행된다.
● 배치 처리(Batch Processing)는 여러 SQL문을 한 번에 실행하여 성능을 향상시키는 방법이다.
● 여러 SQL문을 하나의 배치로 묶어서 데이터베이스에 전송하고 실행한다.
● Statement 및 PreparedStatement를 이용한 배치 처리가 존재한다.
특징
자동화 : 주기적으로 실행되며, 인간의 개입 없이도 일정한 시간에 자동으로 수행된다.
대량 처리 : 대량의 데이터를 한 번에 처리할 수 있다.
비실시간 : 실시간으로 사용자와 상호작용하지 않고, 정해진 시간에 실행된다.
신뢰성 : 정해진 규칙에 따라 안정적으로 데이터를 처리한다.
사용 예시
급여 계산 : 회사의 모든 직원에 대한 월급을 한 번에 계산하고 지급하는 작업.
데이터 마이그레이션 : 한 시스템에서 다른 시스템으로 대량의 데이터를 이전하는 작업.(예:마리아DB → Oracle)
로그 분석 : 서버 로그 파일을 모아서 주기적으로 분석하고 보고서를 생성하는 작업.
package study;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class BatchExample {
public static void main(String[] args) {
// 프로토콜 약속
String url = "jdbc:mysql://localhost:3306/demo3?serverTimezone=Asia/Seoul";
// 응용코드가 데이터베이스에 로그인해야 한다.
String user = "root";
String password = "asd123";
// null인데 실행되면 안되니까 null이 아닐 때만 connection close;
Connection conn = null;
try {
// MySQL 드라이버 로드
Class.forName("com.mysql.cj.jdbc.Driver");
// 자바 표준 API
conn = DriverManager.getConnection(url,user,password);
// 트랜잭션 처리
conn.setAutoCommit(false); // 수동 커밋으로 변경
// 배치 처리 --> users 테이블에 여러 사용자를 한 번에 넣어보기.
String sql = "INSERT INTO users(name,email) VALUES(?,?) ";
PreparedStatement pstmt = conn.prepareStatement(sql);
// 1번 사용자 처리
pstmt.setString(1,"고양이");
pstmt.setString(2, "cat@gmail.com");
pstmt.addBatch(); // 배치 처리하기 위한 메서드가 필요
// 2번 사용자 처리
pstmt.setString(1, "강아지");
pstmt.setString(2, "puppy@hanmail.com");
pstmt.addBatch();
// 3번 사용자 처리
pstmt.setString(1, "햄스터");
pstmt.setString(2, "ham@naver.com");
pstmt.addBatch();
int[] rowCounts = pstmt.executeBatch();
conn.commit(); // 물리적인 저장 장치에 영구히 반영하겠다.
System.out.println("배치 처리 완료 : " + rowCounts.length);
} catch (Exception e) {
e.printStackTrace();
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
try {
if(conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
} // end of main
} // end of class
'Java' 카테고리의 다른 글
DAO,DTO,VO,Entity (0) | 2024.06.21 |
---|---|
JDBC 실습 - CRUD, SOLID, 성능최적화, SQL예외처리, HikariCP (0) | 2024.06.18 |
Parsing(파싱) (0) | 2024.06.10 |
Socket (0) | 2024.06.10 |
공공데이터포탈 사용해보기 (0) | 2024.06.04 |