코드와이
데이터베이스에 관하여 본문
데이터베이스 풀
- Connection Pool
- 클라이어트의 요청에 따라 각 애플리케이션의 스레드에서 DB에 접근하기 위해서는 Connection이 필요하다
- 이런 Connection을 여러 개 생성해 두어 저장하는 공간(캐시)을 말한다.
- 또는 필요한 Connection을 꺼내어 쓰는 기법을 말한다.
- DB 접근
- 웹 컨테이너가 실행되면서 DB와 연결된 Connection 객체들을 미리 생성하여 pool에 저장
- DB에 요청 시 pool에서 Connections객체를 가져와 DB에 접근
- 처리가 끝나면 다시 pool에 반환
- Connection이 부족하면
- 해당 클라이언트는 대기 상태로 전환시키고 Pool에 Connection이 반환되면 대기 상태에 있는 클라이언트들에게 순차적으로 제공된다
- 사용 이유
- 매 연결마다 Connection 객체를 생성하고 소멸시키는 비용 절감
- 미리 생성된 Connection 객체를 사용하기 때문에 DB 접근 시간 단축
- DB에 접근하는 Connection의 수를 제한하여 메모리와 DB에 걸리는 부하를 조정
- Thread Pool vs Connection Pool
- 둘 다 직접적으로 메모리에 관련이 있다.
- 많이 사용할수록 메모리의 많은 부분을 점유하게 된다. 하지만 메모리를 위해 적게 지정하게 되면 서버에서 많은 요청을 처리하지 못하고 대기상태에 있게 된다.
- 모든 요청이 DB Connection 요청이 아니기 때문에 보통 WAS의 Thread 수가 더 많다.
트랜잭션
- 개념
- 데이터베이스의 상태를 변환시키는 하나의 논리적인 작업 단위를 구성하는 연산들의 집합
- 하나의 트랜잭션은 Commit 되거나 Rollback 된다.
- 성질(ACID)
- 원자성(A)
- 트랜잭션의 모든 연산들은 정상적으로 수행 완료되거나 아니면 전혀 어떠한 연산도 수행되지 않은 상태를 보장해야 한다.
- 일관성(C)
- 트랜잭션 완료 후에도 데이터베이스가 일관된 상태로 유지되어야 한다.
- 독립성(I)
- 하나의 트랜잭션이 실행하는 도중에 변경한 데이터는 이 트랜잭션이 완료될 때까지 다른 트랜잭션이 참조하지 못한다.
- 지속성(D)
- 성공적으로 수행된 트랜잭션은 영원히 반영되어야 한다.
- 원자성(A)
- 필요성
- 예) 현금 인출기
- 도중에 기계오류나 정전 등과 같은 예기치 못한 상황이 발생하여 카드가 나오지 않거나 기계가 멈추는 경우
- 각각 다른 은행에서 동시 인출
- 예) 현금 인출기
- 상태
- 활동
- 트랜잭션이 실행 중에 있는 상태
- 장애
- 트랜잭션이 비정상적으로 종료되어 Rollback 연산을 수행한 상태
- 부분 완료
- 트랜잭션이 마지막 연산까지 실행했지만 commit 연산이 실행되기 직전의 상태
- 완료
- 트랜잭션이 성공적으로 종료되어 commit 연산을 실행한 후의 상태
- 활동
트랜잭션 격리 수준
- Isolation level
- 트랜잭션에서 일관성이 없는 데이터를 허용하도록 하는 수준
- 필요성
- 데이터베이스는 ACID 같이 트랜잭션이 원자적이며 독립적인 수행을 하도록 해야한다.
- Locking이라는 개념 등장
- 트랜잭션이 DB를 다루는 동안 다른 트랜잭션이 관여하지 못하게 막는 것
- 무조건적으로 Locking을 통해 많은 트랜잭션을 순서대로 처리하면 성능이 저하된다.
- 반대로 Locking의 범위를 줄이면 잘못된 값이 처리될 여지가 있다.
- 효율적인 Locking 방법이 필요
- 종류
- Read Uncommitted(레벨 0)
- SELECT 문장이 수행되는 동안 해당 데이터에 Shared Lock이 걸리지 않는 Level
- 트랜잭션에 처리 중인 혹은 아직 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 것을 허용한다.
- 예)
- 어떤 사용자가 A라는 데이터를 B라는 데이터로 변경하는 동안 다른 사용자는 아직 완료되지 않은(Uncommitted) 트랜잭션이지만 변경된 데이터인 B를 읽을 수 있다.
- 데이터베이스의 일관성은 유지할 수 없다.
- Read Committed(레벨 1, default)
- SELECT 문장이 수행되는 동안 해당 데이터에 Shared Lock이 걸리는 Level
- 트랜잭션이 수행되는 동안 다른 트랜잭션이 접근할 수 없어 대기하게 된다.
- Commit이 이루어진 트랜잭션만 조회할 수 있다.
- Repeatable Read(레벨 2)
- 트랜잭션이 완료될 때까지 SELECT 문장이 사용하는 모든 데이터에 Shared Lock이 걸리는 Level
- 트랜잭션이 범위 내에서 조회한 데이터의 내용이 항상 동일함을 보장한다.
- 따라서, 다른 사용자는 그 영역에 해당되는 데이터에 대한 수정이 불가능하다.
- Serializable(레벨 3)
- 트랜잭션이 완료될 때까지 SELECT 문장이 사용하는 모든 데이터에 Shared Lock이 걸리는 Level
- 완벽한 읽기 일관성 모드를 제공한다.
- 따라서 다른 사용자는 그 영역에 해당되는 데이터에 대한 수정 및 입력이 불가능하다.
- 레벨이 높아질수록 비용이 높아진다.
- Dirty Read
- commit 되지 않은 수정 중인 데이터를 다른 트랜잭션에서 읽을 수 있도록 허용할 때 발생하는 현상
- 어떤 트랜잭션에서 아직 실행이 끝나지 않은 다른 트랜잭션에 의한 변경 사항을 보게 되는 경우
- Non-Repeatable Read
- 한 트랜잭션에서 같은 쿼리를 두 번 수행할 때 그 사이에 다른 트랜잭션이 값을 수정 또는 삭제함으로써 두 쿼리의 결과가 상이하게 나타나는 비 일관성 현상
- Phantom Read
- 한 트랜잭션 안에서 일정 범위의 레코드를 두 번 이상 읽을 때, 첫 번쨰 쿼리에서 없던 레코드가 두 번째 쿼리에서 나타나는 현상
- 이는 트랜잭션 도중 새로운 레코드가 삽입되는 것을 허용하기 때문에 나타난다.
- Read Uncommitted(레벨 0)
Index
- 개념
- 데이터베이스에서 조회 및 검색을 더 빠르게 할 수 있는 방법/기술
- 필요성
- SELECT문을 사용하여 원하는 조건의 데이터를 검색할 때, 저장된 데이터의 양이 많다면 검색을 위한 순회에 많은 자원과 시간이 소모될 것이다. 이때 도움이 되는 것이 인덱스이다.
- 자주 조회되는 Column에 대한 Index Table을 따로 만들어 SELECT문이 들어왔을 때 Index 테이블에 있는 값들로 결과 값을 조회해 온다. 그래서 Index를 잘 사용한다면 검색 연산을 실행했을 때 성능을 올릴 수 있게 된다.
- 동작 과정
- Index Table에서 WHERE에 포함된 값을 검색
- 해당 값의 table_id PK를 획득
- 가져온 table_id PK값으로 원본 테이블에서 값을 조회
- 주의점
- 인덱스는 따로 테이블의 형태로 관리가 되기 때문에 자원이 소모된다. 때문에 무분별한 인덱스 사용은 성능 저하의 원인이 된다.
- 인덱스는 이진트리를 사용하기 때문에 기본적으로 정렬되어 있다. 이로인해 검색과 조회의 속도를 향상시킬 수 있지만 잦은 데이터의 변경은 인덱스 테이블을 변경과 정렬에 드는 오버헤드 때문에 성능 저하의 원인이 된다.
- 데이터의 중복이 높은 컬럼은 인덱스로 만들어도 무용지물
- 다중 컬럼 인덱싱할 때 카디널리티가 높은 컬럼에서 낮은 컬럼 순으로 인덱싱해야 효율적이다.
파티션
- 개념
- 큰 테이블이나 인덱스를 관리하기 쉬운 partition이라는 작은 단위로 물리적으로 분할하는 것을 의미한다.
- 파티셔닝 기법을 통해 DB를 분산처리하여 성능이 저하되는 것을 방지하고 관리를 보다 수월하게 할 수 있게 되었다.
- 목적
- 성능
- 특정 DML과 쿼리 성능을 향상시킨다.
- 주로 대용량 Data WRITE 환경에서 효율적이다.
- Full Scan에서 데이터 Access의 범위를 줄여 성능 향상을 가져온다.
- 가용성
- 전체 데이터의 훼손 가능성이 줄어들고 데이터 가용성이 향상된다.
- 독립적이고 백업하고 복구할 수 있다.
- table의 파티션 단위로 Disk I/O를 분산하여 경합을 줄이기 때문에 UPDATE 성능을 향상시킨다.
- 관리용이성
- 큰 테이블들을 제거하여 관리를 쉽게 해준다.
- 성능
- 단점
- 테이블 간 조인에 대한 비용이 증가한다.
- 테이블과 인덱스를 별도로 파티셔닝 할 수 없다.
ORM
- 개념
- 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑해주는 것을 말한다.
영속성
- 개념
- 데이터를 생성한 프로그램의 실행이 종료되더라도 사라지지 않는 데이터의 특성
- 영속성을 갖지 않는 데이터는 단지 메모리에서만 존재하기 때문에 프로그램을 종료하면 모두 잃어버리게 된다. 때문에 파일 시스템, 관계형 데이터베이스 혹은 객체 데이터베이스 등을 활용하여 데이터를 영구하게 저장하여 영속성을 부여한다.
Persistence framework
- JDBC 프로그래밍의 복잡함이나 번거로움 없이 간단한 작업만으로 데이터베이스와 연동되는 시스템을 빠르게 개발할 수 있으며 안정적인 구동을 보장한다.
- 종류
- SQL 문장으로 직접 데이터베이스 데이터를 다루는 SQL Mapper
- MyBatis
- 객체를 통해 간접적으로 데이터베이스 데이터를 다루는 객체 관계 Mapper(ORM)
- Hibernate
- SQL 문장으로 직접 데이터베이스 데이터를 다루는 SQL Mapper
JDBC
- 개념
- DB에 접근할 수 있도록 Java에서 제공하는 API
- 과정
- JDBC driver 로딩
- DBMS가 이해할 수 있는 프로토콜로 변환해주는 클라이언트 사이드 어댑터
-
Class.forName("com.mysql.jdbc.Driver");
- Connection 맺기
-
Connection conn = null; conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
-
- SQL 실행
-
// 쿼리 준비 Statement stmt = conn.createStatement(); PreparedStatement pstmt = conn.prepareStatement(SQL_QUERY_STRING);
-
// 쿼리 실행(쓰기 - insert, update, delete) ResultSet rs = stmt.excuteQuery(SQL_QUERY_STRING); // 쿼리 실행(읽기) ResultSet rs = pstmt.executeQuery();
-
// 값 추출 while(rs.next()){ String r1 = resultSet.getString(1); // 컬럼 인덱스 String r2 = resultSet.getString("NAME") // 컬럼명 }
-
- 자원 반환
-
rs.close(); stmt.close(); conn.close();
-
- JDBC driver 로딩
Reference
'기타' 카테고리의 다른 글
Thread란? (0) | 2021.11.29 |
---|---|
디자인 패턴의 개념과 종류 (0) | 2021.11.29 |
Maven & Gradle (0) | 2021.11.29 |
Web Server vs WAS (0) | 2021.11.29 |
형상관리 툴(CVS, SVN, Git) (0) | 2021.11.29 |