SQL Injection

  • 클라이언트의 입력 값을 조작하여 서버의 데이터베이스를 공격할 수 있는 보안 공격방법
  • 사용자의 입력 데이터를 제대로 필터링 하지 않을 경우 발생
  • ex. 'OR '1' = '1' 으로 아이디와 비밀번호가 올바르지 않아도 로그인
SELECT user FROM user_table WHERE id='admin' AND password=' ' OR '1' = '1';

 

방어 방법

  • 유저에게 받은 값을 바로 SQL에 넘기지 않는다.
  • input 값을 받고, 특수 문자 여부 검사
  • SQL server 오류 발생 시, 에러 메시지 감추기
    • view를 활용하고, 원본 DB 접근 권한 높이기
  • 요즘 사용하는 DB들은 유저 입력이 의도치 않은 동작을 하지 않도록 escape 함수와 prepared statement 제공
    • prepared statement : 변수를 문자열로 바꾸는 것. 특수 문자를 자동으로 escape
    • statement와 다르게 쿼리문의 전달 값을 ?으로 받는다. 서버 측에서 필터링 후 공격 방어

 

prepared statement 

  • 준비(prepare) : 먼저 애플리케이션에서 문의 틀을 만들고, DBMS에 보낸다.
    • 특정 값은 지정하지 않은 채로 남겨지고, 이 값들을 '변수', '플레이스홀더', '바인드 값'으로 부른다.
  • 그 후에 DBMS에서 문의 틀을 컴파일 하고, 결과만 저장한다.
  • 실행(Excute) : 나중에 애플리케이션에서 바인드 값을 지정하면, DBMS은 결과를 반환할 수도 있는 문을 실행한다. 
INSERT INTO product (name, price) VALUES (?, ?);

 

Java JDBC 예시

import java.sql.PreparedStatement;

PreparedStatement pstmt;
String sql = "INSERT INTO usertbl VALUES (?, ?)";
pstmt = con.prepareStatement(sql);

pstmt.setString(1, 'userId123'); // userId
pstmt.setInt(2, 010-1234-5678) // phoneNum
pstmt.executeUpdate();

 

 

레디스(Redis) Remote Dictionary Server

- key value 구조의 비정형 데이터를 저장하고 관리하기 위한 오픈 소스 기반의 비관계형 DBMS

- 메모리 기반 DBMS

- 대부분의 DB는 하드디스크나 SSD에 저장하지만, 레디스는 메모리(RAM)에 저장해서 디스크 스캐닝 없이 매우 빠름

- 캐싱이 가능해서, 실시간 채팅에 적합

- 세션 공유를 위해 세션 클러스터링에도 활용

- 데이터 구조 : key value

 

value 종류 5가지

- String (text, binary data)

- set (String 집합)

- sorted set

- hash

- List

 

휘발성(RAM) 방지 방법

- snapshot : 특정 지점을 설정하고 디스크에 백업

- AOF(Append Only File) : 쿼리를 저장해두고, 서버 셧다운 시 재실행 해서 다시 만든다.

 


캐싱(Caching)

  • 이미 가져온 데이터나 계산된 결과 값의 복사본을 저장해서 처리 속도를 향상시키고, 이후의 요청을 더 빠르게 처리할 수 있다.
  • 요청에 대한 결과를 임시적으로 저장하는 행위
  • 장점 : 성능 향상, 부하 방지
  • 활용 예시
    • 반복적이고 동일한 결과가 나오는 기능의 반환 값
    • 업데이트가 자주 발생하지 않는 데이터
    • 자주 조회되는 데이터
    • 입력 값과 출력 값이 일정한 데이터
    • 캐싱된 데이터는 데이터 갱신으로 DB 불일치 발생 위험이 있다.

 

로컬 캐시(Local Cache)

  • 서버마다 캐시를 따로 저장
  • 다른 서버 캐시 참조는 어렵다.
  • 서버 내에서 작동하기 때문에 속도가 빠르다.
  • local server의 리소스 사용(memory, disk)
  • 캐시에 저장된 데이터가 변경되는 경우
    • 해당 서버 제외 모든 peer 에 변경 사항 전달
    • all - to - all replication
    • WAS 인스턴스가 증가하고, 캐시 저장 데이터가 커지면 성능 저하되는 이유

 

글로벌 캐시(Global Cache)

  • 여러 서버에서 캐시 서버에 접근하여 참조 가능
  • 별도 캐시 서버를 이용한다. 서버 간 데이터 공유가 쉽다.
  • 네트워크 트래픽을 사용하기 때문에, 로컬 캐시보다 느리다.
  • 데이터를 분산하여 저장 가능
    • Replication : 두 개 이상의 DBMS 시스템을 master/slave으로 나눠서 동일한 데이터를 저장
    • Sharding : 같은 테이블 스키마를 가진 데이터를 다수의 DB에 분산하여 저장하는 방법
  • 캐시에 저장된 데이터가 변경되는 경우
    • WAS 인스턴스 증가, Cache 데이터 크기가 커질 수록 효과적인 이유

JOIN

- 두 개 이상의 테이블에서 데이터가 필요한 경우 조인 사용

 

(1) INNER JOIN 

- 일반적인 JOIN

- 교집합

 

(2) OUTER JOIN

- LEFT, RIGHT, FULL

- JOIN 조건을 만족하지 않는 행을 포함한다.

 

- Left join : (A-B) + AnB

 

- Right join : (B-A) + AnB

- Full outer join : 합집합

(3) SELF JOIN

- 같은 테이블에서 2개의 속성을 연결하여 조인

 

 

(4) CROSS JOIN

- 일반적으로 많이 사용하지 않는다.

- 한 쪽 테이블과 다른 테이블의 모든 행들을 조인한다.

- 더미데이터 생성에 사용

 

 

(5) Natural JOIN 

- 두 테이블의 동일한 이름을 가지는 칼럼이 모두 조인된다.

- Inner join 과의 차이로는 natural join은 조인에 사용된 같은 이름의 칼럼을 하나로 처리하지만, inner join은 별개의 칼럼으로 표시

 

 


UNION

- 다수의 SELECT 문을 합칠 경우 사용한다.

- Union : 중복 제거

- Union all : 중복 허용

 

 

JOIN 과 UNION 차이

- 조인은 두 릴레이션 속성을 결합하여 결과 튜플을 생성한다.

- 유니온은 두 쿼리의 결과를 합친다.

키(Key)

  • 검색, 정렬 시 Tuple을 구분할 수 있는 기준이 되는 Attribute

 

후보 키(candidate key)

  • 관계형 데이터베이스에서 슈퍼키 중 더 이상 줄일 수 없는 형태를 가진 것
  • Tuple을 유일하게 식별하기 위해 사용하는 속성들의 부분집합
  • 조건
    • 유일성 : key 하나로 tuple을 유일하게 식별 
    • 최소성 : 꼭 필요한 속성으로 구성

 

 

기본 키(Primary key)

  • 관계형 데이터베이스에서 레코드의 식별자로 이용
  • 후보키 중에 선택한 main key <-> 대리키 : 기본키가 아닌 후보키
  • 특징
    • Null 허용
    • 동일한 값 중복 X (UNIQUE)

 

외래 키(Foreign Key)

  • 한 테이블의 필드(attribute) 중 다른 테이블의 행을 식별할 수 있는 키
  • 다른 릴레이션의 기본키를 그대로 참조하는 속성의 집합

 

슈퍼 키(Super Key)

  • 관계(테이블)의 행을 고유하게 식별할 수 있는 속성 또는 속성의 집합
  • 유일성은 만족하지만, 최소성은 만족하지 않는다. -> 둘다 만족하면 후보키

 

대리 키(Alternate Key) = 보조 키

  • 관계형 데이터베이스에서 후보키 중에 기본키로 선정되지 않은 키

SQL(RDBMS)

  • 관계형 데이터베이스 특징
    • 데이터는 정해진 데이터 스키마에 따라 테이블에 저장
    • 관계에 따라 여러 테이블에 분산된다.
    • 데이터의 중복을 피하기 위해 관계를 이용
  • 구조
    • 필드의 이름
    • 데이터의 유형

 

NoSQL

  • 비관계형 데이터베이스 사용
  • 스키마와 관계 사용 X
  • documents(도큐먼트) : SQL의 record
    • JSON과 비슷한 형태
    • ex. SQL : ORDER_TB, USERS_TB, PRODUCT_TB
    • ex. NoSQL : ORDER_TB에 모두 저장 -> JOIN을 하지 않는다.(데이터의 중복)
  • NoSQL은 다른 구조의 데이터를 같은 컬렉션에 추가 가능 <-> SQL는 정해진 스키마를 따라야 데이터 추가 가능
  • 대량의 분산 데이터를 저장하고 조회에 특화
    • 메모리나 임시 파일에 저장 후 클라이언트에 먼저 응답하는 방법을 지원. 스케일 아웃 지원
  • 가용성을 보장하기 위해 데이터 복제(Replication) 사용
    • 동일한 데이터를 다중 노드에 중복 저장하고, 다른 노드가 고장나도 데이터가 유실되지 않게 하는 방법
    • Master slave, Peer to Peer

 

SQL, NoSQL 

  • 수직적 확장 : 물리적 서버 성능 향상(CPU 업그레이드) -> SQL
  • 수평적 확장 : 분산된 데이터베이스와 서버 추가  -> NoSQL
  • SQL 장단점
    • 장점 : 명확한 스키마, 데이터 무결성, 관계 사용으로 데이터 중복 X
    • 단점 : 유연성 X, 번거로운 스키마 정의, 복잡한 JOIN문 발생 위험, 수직적 확장의 한계
  • NoSQL 장단점
    • 장점 : 스키마가 없어서 유연함, 빠른 데이터 조회, 수직 및 수평 확장 가능
    • 단점 : 유연성으로 인해 데이터 구조 결정을 미루게 될 수 있다. 데이터 중복을 계속 업데이트 해야 한다. 데이터 수정 시 모든 컬렉션에서 수행

트랜잭션(Transaction)

  • 데이터베이스 상태를 변화시키기 위해 수행하는 작업 단위
  • 작업의 완전성을 보장해준다. 
  • 상태 변화 : SQL query를 통해 DB에 접근(SELECT, INSERT, DELETE, UPDATE)
  • 작업 단위 : 많은 SQL 명령문들을 사람이 정하는 기준에 따라 정하는 것
    • ex. A 사용자가 B 사용자 에게 x원 송금
    • A 계좌에서 - (x원) UPDATE
    • B 계좌에서 + (x원) UPDATE
    • 현재 작업 단위(트랜잭션) : + UPDATE, - UPDATE
    • Commit : 두 쿼리문이 모두 성공되면 하나의 작업 완료 
    • Rollback : 하나라도 실패시, 모든 쿼리문을 취소하고 이전 상태로 돌려놓기

 

트랜잭션, Lock

  • Lock : 동시성을 제어하기 위한 기능
    • 여러 곳에서 동시에 동일한 자원을 요청할 때, 하나의 커넥션만 변경할 수 있도록 해준다. 
  • 트랜잭션 : 데이터의 정합성을 보장하는 기능
    • 하나라도 실패하면 적용되지 않도록 보장

 

트랙잭션의 특성 - ACID

(1) Atomicity(원자성)

- All or nothing

- 모든 작업이 완료되거나 실행이 아무것도 되지 않아야 한다.

 

(2) Consistency(일관성)
- 트랜잭션이 끝난 후, 결과가 제약조건에 위배 되지 않는 상태(correct state)이 된다.

 

(3) Isolation(독립성)

- 모든 트랜잭션이 다른 트랜잭션에 독립적이다.

- Thread 동기화 처리와 일치한다.

 

(4) Durability(지속성)

- 트랜잭션 성공적으로 종료 시, 해당 결과가 2차 저장소에 영구적으로 저장된다.

 

 

트랜잭션 사용 주의사항

  • 꼭 필요한 최소의 코드에만 적용한다. = 트랜잭션 범위 최소화
  • 각 단위 프로그램의 커넥션 소유 시간이 길어지면, 다른 프로그램에서 커넥션을 가져가게 되면 대기 시간이 길어질 수 있다.

 

 

트랜잭션 격리 수준(Transaction Isolation Level)

  • 트랜잭션에서 일관성 없는 데이터를 허용하도록 하는 수준
  • 데이터베이스는 ACID의 특징처럼, 트랜잭션은 독립적인 수행이 이루어져야 한다.
  • Locking을 통해, 하나의 트랜잭션에 다른 트랜잭션이 관여하지 못하도록 막을 수 있다.
  • 하지만, Locking은 데이터 베이스의 성능을 저하시킬 수 있는 단점이 있다. -> 효율적인 Locking 필요 

 

 

Isolation level

  • level 0 : 트랜잭션이 처리중이거나, 아직 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 것 허용
  • level 1 : commit이 이루어진 트랜잭션만 조회 가능 (대부분 SQL server의 default)
  • level 2 : 트랜잭션이 완료되기 전까지 다른 사용자는 데이터 수정 불가능 (MySQL default)
  • level 3 : 다른 사용자는 트랜잭션 영역에 해당되는 데이터에 대한 수정 및 입력 불가능

 

교착상태

  • 2개 이상의 트랜잭션이 특정 자원의 lock을 획득한 채 다른 트랜잭션이 소유하고 있는 lock을 요구하면 계속 기다려도 상황이 바뀌지 않는 상태
  • 교착 상태의 빈도를 낮추는 방법
    • 트랜잭션을 자주 커밋한다.
    • 정해진 순서로 테이블에 접근
    • 읽기 잠금 획득(SELECT ~ FOR UPDATE) 사용 피하기
    • 한 테이블의 복수 행을 복수의 연결에서 순서 없이 갱신하면 교착상태 발생 
      • 테이블 단위의 잠금으로 갱신을 직렬화 한다. but 동시성 저하

정규화(Normalization)

  • 데이터의 중복을 줄이고, 무결성 향상, 이상 현상을 방지한다.

 

이상 현상(Anomaly)

  • 잘못된 정규화로 데이터의 중복이 발생되고, 무결성이 저하되는 현상
  • 삽입 이상(Insertion Anomaly)
    • 기본키가 {Studnet ID, Course ID} 일 때, Course를 수강하지 않은 학생은 Course ID가 없음.
    • 기본키는 Null이 될 수 없어서 테이블에 추가 불가능
  • 갱신 이상(Update Anomaly)
    • 어떤 학생의 전공이 A에서 B로 바뀌는 경우, 모든 A를 B로 바꿔야 한다. 하지만 일부가 바뀌지 않는 형상
  • 삭제 이상(Deletion Anomaly)
    • 어떤 학생이 수강을 삭제할 때, {Student ID, Department, Course ID, Grade} 정보 중에 Student ID, Department와 같은 학생에 대한 정보도 삭제 된다.

 

 

제1 정규화(1NF)

  • 테이블 칼럼이 원자값(하나의 값)을 갖도록 테이블을 분리시키는 것
  • 릴레이션에 속한 모든 도메인이 원자값으로만 되어 있어야한다.
  • 모든 속성에 반복되는 그룹이 나타나지 않는다.
  • 기본키를 사용하여 관련 데이터의 각 집합을 고유하게 식별 가능해야 한다.

 

제2 정규화(2NF)

  • 제 1정규화를 만족하고, 테이블의 모든 칼럼이 완전 함수적 종속을 만족해야 한다.
  • 기본키가 복합키(키1, 키2) 일 때, 두개의 키 중 하나의 키만 남긴다.

 

제3 정규화(3NF)

  • 제 2정규화를 만족하고, 진행된 테이블에서 이행적 종속을 없애기 위해 테이블을 분리한다.
  • A -> B, B -> C 이면 = A -> C

 

정규화의 장점과 단점

  • 장점
    • 데이터베이스를 변경 할 때, 이상 현상을 방지할 수 있다.
    • 데이터베이스를 확장할 때, 정규화 데이터베이스는 일부만 변경해도 된다. 
  • 단점
    • 릴레이션의 분해로 인해, 릴레이션 간의 연산(JOIN)이 증가하게 된다. -> 응답 시간 저하
    • 과도한 정규화와 데이터 입력/수정/삭제 연산이 잦으면, 데이터 처리 속도가 느려저 응답 시간 저하 or 데이터 무결성 X

 

반정규화

  • SQL에서 잦은 조인으로 성능 저하가 나타나는 경우에 반정규화 사용
  • 자주 사용되는 테이블에 접근하는 프로세스 수가 많고, 항상 일정한 범위만 조회하는 경우 사용
  • 테이블에 대량 데이터가 있고 대량의 범위를 자주 처리하는 경우
  • 테이블에 지나친 조인으로 데이터 조회가 어려울 경우

 

 

 

Index(인덱스)

  • 추가적인 쓰기 작업과 저장 공간을 활용하여 데이터베이스 테이블의 검색 속도를 향상시키기 위한 자료구조
  • 테이블의 칼럼과 해당 레코드가 저장된 주소를 key-value 쌍으로 인덱스를 만들어 둔다.
  • DBMS 인덱스는 값 탐색(SELECT)은 빠르지만, 값의 삭제, 추가, 수정(Update, Delete, Insert)의 경우에는 쿼리문 실행 속도가 느려진다.

 

Index 자료구조

  • B+-Tree 인덱스 알고리즘
    • 일반적으로 사용되는 인덱스 알고리즘
    • 칼럼의 값을 변형하지 않고, 원래의 값을 이용해 인덱스하는 알고리즘
  • Hash 인덱스 알고리즘
    • 칼럼의 값으로 해시 값을 계산해서 인덱싱하는 알고리즘
    • 주로 메모리 기반의 데이터 베이스에서 사용
  • B+-Tree 를 사용하는 이유는?
    • SELECT query에 부등호(<>) 연산도 포함되기 때문에 hash table에서 사용하기 적합하지 않다.

 

Primary index(기본 인덱스), Secondary index(보조 인덱스)

  • 클러스터(Cluster) : 여러 개를 하나로 묶는 의미
  • 클러스터드 인덱스 
    • 인덱스에서 비슷한 것을 묶어서 저장하는 형태
    • 클러스터드 인덱스는 테이블의 primary key에만 적용
    • primary key 값이 비슷한 레코드끼리 묶어서 저장하는 것
    • 테이블 당 한 개만 생성 가능하다. <-> 논 클러스터드 인덱스는 테이블 당 여러개 생성 가능

 

 

테이블 생성 시 파일 구성

  • FRM : 테이블 구조 저장 파일
  • MYD : 실제 데이터 파일
  • MYI : Index 정보 파일(Index 사용시 생성)
    • 쿼리로 index를 사용하는 칼럼을 검색하면, MYI 파일의 내용을 활용

 

인덱스 단점

  • index를 생성하면, .mdb 파일 크기가 증가한다.
  • 한 페이지를 동시에 수정할 수 있는 병행성 감소
  • 데이터 변경이 자주 일어날 경우 index의 재작성으로 성능 저하

 

 

인덱스 활용 예시

  • 사용하면 좋은 경우
    • where 절에서 자주 사용되는 경우
    • 외래키가 사용되는 경우
    • join 에 자주 사용되는 경우
  • Index 사용하면 안좋은 경우
    • Data 중복도가 높을 경우
    • DML이 자주 일어나는 경우(Insert, Delete, Update)

 

DML 요청 시 상황

  • INSERT
    • 기존 block에 여유가 없으면 새로운 data 입력
    • 새로운 block을 할당 받고, Key를 옮긴다.
    • index split 작업 동안, 해당 block의 key 값에 대해 DML 블로킹
  • DELETE
    • table에서 data 삭제 : data는 지워지고, 다른 Data가 공간 사용 가능
    • index에서 data 삭제 : data가 지워지지 않고, 사용 안됨으로 표시된다.
  • UPDATE
    • table에서 update : index는 update 불가능
    • index에서 update : delete 발생 후, 새로운 작업 insert (table보다 2배 작업)

+ Recent posts