22 년 기준 Amazon Linux2 는 CentOS 기반으로 되어있으며, 기본적으로 Yum Repository 에는 MySQL 서버의 패키지 경로가 존재하지 않는다.

따라서 먼저 Amazon Linux2 서버 위에 Yum Repository 를 추가해준다.

 

sudo yum install https://dev.mysql.com/get/mysql80-community-release-el7-5.noarch.rpm

 

Yum Repository 가 등록되었다면 다음 명령어를 통해 MySQL Community Server 를 구축해준다.

 

sudo amazon-linux-extras install epel -y
sudo yum -y install mysql-community-server

 

다음으로는 EC2 위에서 MySQL 서비스를 실행시켜준다.

 

sudo systemctl enable --now mysqld

 

서비스의 실행 상태는 다음 명령어로 확인할 수 있다.

 

systemctl status mysqld

 

MySQL 서버는 초기에 Root 계정만 존재하며, 임시 비밀번호가 발급된 상황이다. 

초기에 해야할 일은 임시 비밀번호를 대체하고, 실제 데이터베이스에 접근할 사용자 계정을 만드는 일이다.

 

sudo grep 'temporary password' /var/log/mysqld.log

명령어를 치게 되면 다음과 같이 임시 비밀번호가 튀어나온다.

임시 비밀 번호를 이용해서 MySQL 서버에 접속한다.

mysql -uroot -p

위와 같이 명령어를 입력하면 localhost 에 루트 계정으로 접속을 시도하게 된다. 비밀번호 창이 나오면 임시 비밀번호를 입력해준다.

 

초기에 MySQL 에 들어가면 가장 먼저 해야할 일은 루트 비밀번호를 변경하는 것이다. 이를 하지 않고는 사실상 아무 작업도 하지 못한다.

ALTER user 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '변경할 비밀번호';

다음 명령어를 입력해서 권한을 반영해준다.

FLUSH PRIVILEGES;

 

- 슈퍼 유저 만들기

 

Root 계정으로 MySQL 에 접근하는 건 안전하지 못하며, 필요한 권한만 가진 데이터베이스 사용자 계정을 만드는 것이 좋다.

다음 명령어를 통해 사용자 계정을 만든다.

create user '<계정 이름>'@'%' identified by '<비밀번호>';

원래는 가져야하는 권한만 정의해서 사용자 계정을 만들어야하지만, 이번 포스팅에서는 슈퍼 유저를 만들어보도록 한다.

다음 명령어를 사용하면 모든 데이터베이스에 대한 모든 권한을 사용자가 어디에서 접근하던지 부여할 수 있다.

GRANT ALL PRIVILEGES ON *.* to '<계정 이름>'@'%';

마찬가지로 설정 이후에는 다음 명령어로 권한을 반영해주도록 한다.

FLUSH PRIVILEGES;

 

 

참고 : 

https://techviewleo.com/how-to-install-mysql-8-on-amazon-linux-2/

 

OLTP 와 OLAP 는 개발자로서 생각보다 친숙한 개념임에도 불구하고 실제로 많이 사용되는 단어가 아니다보니 생소한 경우가 많다.

 

* OLTP (Online Transaction Processing)

 OLTP 란 온라인 트랜잭션 처리를 말하며, 네트워크 상의 온라인 사용자들의 Database 에 대한 일괄 트랜잭션 처리를 의미한다. 

흔히 말하는 "트랜잭션(Transaction) 처리" 를 OLTP 라 부른다. 트랜잭션이라 부르는 용어의 의미 자체가 OLTP 의 의미를 포함하고 있다고 할 수 있겠다. 

Transaction 에 대한 보다 자세한 설명은 다음 포스팅을 참조해보자.

https://jins-dev.tistory.com/entry/Database-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98%EC%9D%84-%EC%9C%84%ED%95%9C-ACID-%EC%9D%98-%EA%B0%9C%EB%85%90

 

트랜잭션의 주 특징은 그루핑된 연산의 실패시, Rollback 이 지원된다는 점이다.

주로 기술적 특성상, 대규모의 처리보다는 소규모의 정교한 데이터 구성이 필요한 데이터의 처리가 중점이 된다.

 

 

* OLAP (Online Analytical Processing)

 OLAP 란 Database 자체적으로 운용되는 시스템이라기 보다는 데이터 웨어하우스 등의 시스템과 연관되어 Data 를 분석하고 의미있는 정보로 치환하거나, 복잡한 모델링을 가능하게끔 하는 분석 방법을 말한다.

 

기능 자체에 중심을 두는 OLTP 와는 다르게 사용하는 목적과 주제에 보다 중점을 둔다.

그렇기 때문에 주로 대용량의 데이터에 대해 처리하고 보다 복잡한 Data processing 으로 의미를 추출하는데 중점을 둔다.

 

대부분의 경우 OLAP 연산을 수행한다 라고 하면 적재된 데이터에 대한 분석 또는 SELECT Query 를 통한 데이터 스캔 Operation 이 주가 된다. 이는 OLTP 가 Transaction 의 과정에서 INSERT/UPDATE 를 중점적으로 수행하는 것과 대조되게 된다.

(하지만 언급했듯이, 쿼리의 읽기냐 쓰기냐 에 따라 구분되는 개념이라고 보기는 애매하다!)

 

 

면접에서 물어보면 트랜잭션은 알아도 OLTP 는 모르는 경우가 많다..

용어 자체가 중요하다고 보지는 않지만 알아둘 필요가 있겠다.



RDB 를 포스팅할 때 가장 먼저 정리해야 하는 부분인데 다소 순서가 밀렸다... 


이번 포스팅에서는 Database 를 다루는 데 있어서 가장 기본적인 Table 의 Key 에 대해 정리한다.


Database 에서 Key 의 의미는 테이블에서 각 데이터를 분류하는 기준의 역할을 한다.


MySQL 에서는 테이블의 데이터 들을 구분하기 위한 키의 종류로 다음과 같은 종류들을 사용한다.


(1) Key(Index)

 가장 일반적인 Key 는 DB 의 Index 와 동의어이다. Database 는 데이터의 검색을 위해 Index 를 색인으로 사용하므로 중요한 역할을 한다.

 중복을 허용하며 NULL 등의 허용도 가능하지만 NULL 이 허용될 경우... 색인에 있어 비약적인 성능 저하를 가져오므로 일반적으로 Nullable 한 데이터의 경우 Indexing 하지 않는다.

 단순히 Key, 즉 Index 로만 지정할 경우에는 별도에 제약조건(Constraint)을 가지지 않기 때문에 테이블 내에 데이터에 대해 엄격한 정합성이 요구될 경우에는 적합하지 않다.



(2) Primary Key

 일반적인 Key 는 Index 를 지칭하지만, 일반적으로 DB 설계를 할 때 Key 라고 하면 보통 PK 를 의미한다.

 NULL 을 허용하지 않고, Unique 성질을 지니므로 NOT NULL & UNIQUE 옵션이 포함되며 테이블 당 단 하나의 정의만 가질 수 있다.

 즉, PK 로 단 하나의 칼럼이 지정되어 있다면 해당 칼럼의 데이터는 Table 내에서 유일성이 보장되며 

 여러 개가 PK 로 지정되어 있다면 해당 Key 들의 조합에 대해 유일성이 보장된다.

 따라서 PK 는 같은 PK 를 갖는 행을 테이블 내에서 고유하게 만든다.


 기본적으로 Index 성질 역시 보장되기 때문에 검색 시 색인의 Key 가 되며, Constraint 를 갖기 때문에 다른 테이블과 JOIN 을 할 때 기준 값으로 사용된다.

 RDB 의 특징적인 데이터 정합성의 보장과 Key 값의 성질을 갖기 때문에 일반적인 설계에서도 가장 선호되는 Key 타입이다.



(3) Unique Key

 Unique Key 는 Uniqueness 를 지닌 Index를 말하며, Unique Index 라 부르기도 한다.

 PK 와 마찬가지로 중복성이 허용되지 않지만 NULL 에 대한 허용이 가능하다.

 테이블 당 여러개를 가질 수 있다.



(4) Foreign Key

 Foreign Key 란 JOIN 등으로 다른 DB 와의 Relation 을 맺는 경우, 다른 테이블의 PK를 참조하는 Column 을 FK 라고 한다.

 여기서 Foreign Key Relation 을 맺는 다는 의미는 논리적 뿐 아니라 물리적으로 다른 테이블과의 연결까지 맺는 경우를 말하며, 이 때 FK 는 제약조건(Constraint)으로의 역할을 한다.

 Foreign Key Restrict 옵션을 줄 수 있고 다음과 같은 옵션들이 있다.


  - RESTRICT : FK 관계를 맺고 있는 데이터 ROW 의 변경(UPDATE) 또는 삭제(DELETE) 를 막는다.


  - CASCADE : FK 관계를 맺을 때 가장 흔하게 접할 수 있는 옵션으로, FK 와 관계를 맺은 상대 PK 를 직접 연결해서 DELETE 또는 UPDATE 시, 상대 Key 값도 삭제 또는 갱신시킨다.

  이 때에는 Trigger 가 발생하지 않으니 주의하자.


  - SET NULL : 논리적 관계상 부모의 테이블, 즉 참조되는 테이블의 값이 변경 또는 삭제될 때 자식 테이블의 값을 NULL 로 만든다. UPDATE 쿼리로 인해 SET NULL 이 허용된 경우에만 동작한다.


  - NO ACTION : RESTRICT 옵션과 동작이 같지만, 체크를 뒤로 미룬다.


  - SET DEFAULT : 변경 또는 삭제 시에 값을 DEFAULT 값으로 세팅한다.



주로 PK 가 설계 시 많이 이용되지만, 정합성이 중요하지 않은 경우 Index 만 이용해서 테이블을 설계하기도 한다.

UNIQUE Index 는 주로 복잡한 테이블에서 부분적인 정합성을 살리기 위해 많이 이용된다.

그리고 FK 의 물리적 연결은 서버의 안정성을 위해 지양하는 편이 많다.


상황에 알맞게 적합한 Key 를 잡아 설계하는 것이 최선의 튜닝 기법이라고 생각된다.



 Char형의 뒤에는 캐릭터 형의 길이를 명시하기 위해 (숫자) 와 같은 형식으로 값이 붙게 되는데 Int형 뒤에도 붙일 수 있다. 


하지만 Int형의 괄호는 숫자 개수의 제약을 의미하는 것이 아니라 Zerofill을 위한 것이다. 


예를 들어 Int(5)는 5자리 내 숫자는 모두 0으로 채워준다는 뜻이다. 단 ORACLE에서는 실제 자리 수를 표현하는데 사용된다.





Data Replication은 데이터를 물리적으로 다른 서버 공간에 복제하는 일이다. 

이를 잘 이용하면 부하 분산 및 고가용성, 버전 테스트 등 멋지게 사용할 수 있는 방안이 많아진다. 

일반적으로 하나의 Master와 여러 개의 Slave로 이루어진 구조에서 Read Only인 Slave 노드들에 Write 가능한 Master의 데이터가 업데이트되면 동기화시키는 방향으로 복제가 이루어진다.


Database Replication 은 기본적으로 비동기(Asynchronous)로 이루어진다.


Replication 은 대게 Writable 한 Master Node 에서 Readonly인 Slave로 이루어진다.


Replication 으로 인한 이점들에는 다음과 같은 것들이 있다.


- Scale out solution : Replication 을 통해 Read 요청에 대한 분산을 여러 Slave 로 나눔으로써 병목현상을 해결할 수 있다. 


- Data security : 데이터가 Slave로 복제됨에 따라서 마스터 서비스에 대한 영향 없이 데이터에 대한 백업이 가능하다.


- Analytics : 서비스에 영향을 미치지 않고 데이터 분석이 용이하다.


- Long-distance data distribution : Data를 여러 지리적 Location 혹은 Local에 Copy 를 만들 수 있다. 이는 자연적 재해나 지리적 장애에 대한 대응책이 될 수 있다.



MySQL 의 Replication은 로그 기반으로 비동기적으로 데이터를 복제한다. 


마스터에서는 데이터가 변경되면 Binary Log라는 곳에 이력을 기록하는데, 실행된 SQL을 그대로 기록하거나(Statement-Based), 변경된 행을 Base64로 인코딩하여 기록하거나(Row-Based), 적절히 혼합한형태(Mixed Type)로 동기화를 수행한다. 


(1) Master에서 데이터 변경이 일어나면 자신의 데이터베이스에 반영한다.


(2) Master에서 변경된 이력을 Binary Log에 기록한 뒤 관련 이벤트를 날린다.


(3) Slave IO_THREAD에서 Master 이벤트를 감지하고 Master Binary Log의 Relay Log에 기록한다.


(4) Slave SQL_THREAD는 Relay Log를 읽고 자신의 DB에 기록한다.



마스터에서는 여러 세션에서 데이터 변경처리가 가능하지만 Slave에서는 오직 SQL Thread에서만 데이터 변경처리가 이루어질 수 있기 때문에 Master의 데이터 변경 트래픽이 과도할 경우 동기화 시간 차이가 크게 날 수도 있다.


동일한 Database 소스를 여러 군데에 분산시키는 점은 개발자가 API 를 구현할 때에도 신경써주어야 하는 부분이다.


WAS 레벨에서 어떤 DB를 바라볼지에 대한 문제는 보통 Web Framework 레벨에서 지원해주는 경우가 많다. 가장 간단한 방법으로는 서로 다른 커넥션 풀을 만들어 쿼리를 날릴때마다 직접 분기해주는 방법이지만 이는 비효율적이며 비생산적이다.


먼저 Spring을 사용하면 @Transactional(readOnly=true) 라는 어노테이션에서 readOnly 옵션을 이용해서 트랜잭션 설정 하나로 서로 다른 데이터 소스로 연결시킬 수 있다. 

또한 Spring의 AbstractRoutingDataSource 클래스는 여러 개의 DataSource를 하나로 묶고 자동으로 분기처리해주는 Spring 기본클래스이다. 이를 이용해서 @Transactional 과 잘 연계하면 쉽게 분기처리가 가능하다.


참고로 Spring의 @Transactional 처리는 TransactionManager 선별 -> DataSource에서 Connection 획득 -> Transaction 동기화 순으로 일어나기 때문에 커넥션을 동기화 이후에 얻는 Lazy 한 방식을 사용해야 함을 명심한다.



본 포스팅에서 언급한 내용은 Master-Slave Replication 이지만, 경우에 따라 Master-Master Replication 을 구조로 구성하기도 한다.

Master-Master replication 구조를 고려할 때에는 Master 간 Conflict 및 데이터베이스에서의 ACID 성질의 유지가 힘들기 때문에 신경쓸 부분이 조금 더 많다. 

그렇기 때문에 Master-Master Replication 의 경우 Active Directory / LDAP 과 같은 Directory Service Server 나 Data 의 Conflict 우려가 적고 Accessibility 가 중요한 서비스의 경우 고려된다.

(참조 : https://stackoverflow.com/questions/3736969/master-master-vs-master-slave-database-architecture)



클라우드 환경이 도입되면서 Multi A-Z 에서의 Replication 전략도 눈여겨 봐야하는데, 보통 하나의 Master 를 한 Availability Zone 에 두고 Read-only Slave 들을 같은 Zone 및 다른 AZ 에 배치시켜두는 형태를 취한다. AWS 에서는 이를 Read-Replica 라는 서비스로 제공한다.



두 테이블의 참조 관계에서, A B테이블의 관계가 1:N Relationship을 맺을 때, A 테이블의 해당 키를 참조키(Reference Key)라 하고, B 테이블의 해당 키를 외래키(Foreign Key)라 한다

ON DELETE/UPDATE 시 적용될 Cascade 의 종류는 다음과 같이 분류된다.


(1)  CASCADE : 참조키가 삭제/수정 되면 외래키도 삭제/수정된다.


(2)  RESTRICT : 참조키가 삭제/수정 되는 것을 방지한다.


(3)  SET NULL : 참조키가 삭제/수정 시 NULL로 만든다.


(4)  NO ACTION : 참조키가 삭제/수정 시 변동이 안생긴다.


실무에서는 물리적으로 FK를 적용하는 경우가 드물기 때문에 복잡한 종류의 마스터 데이터이거나 비즈니스 로직보다 데이터의 일관성이 중요한 경우가 아니라면 잘 사용은 안한다. 

하지만 물리적으로 연결하게 된다면 상황에 따라 FK 참조 방식을 설정할 때가 있다. 잘 알아두어서 필요할 때 적절하게 사용할 필요가 있다.



 MyBatis 를 접하고 업무를 할 때 대부분의 일은 Sql Mapper 를 만들고, SELECT, INSERT, UPDATE, DELETE 와 같은 CRUD 작업을 위한 DML(Data Manipulation Language) 를 작성하는 업무이지만, 간혹 Create Table, Drop Table 과 같은 DDL(Data Definition Language) 을 작성해야할 경우가 있다.


 Mybatis를 이용해서 DDL 쿼리도 적용이 가능하다. 

예를들어 CreateTable / DropTable / ShowCreateTable / DescTable 등인데 이 내용이 Mybatis 백서에도 제대로 안나와있다.

결론적으로 말하면 그냥 사용하면 되는데, 사용방법은 다음과 같다.



<select id="existTable" resultType="Integer">
SELECT count(TABLE_NAME)
FROM
INFORMATION_SCHEMA.TABLES
where
TABLE_SCHEMA = #{databaseName, jdbcType=VARCHAR}
AND
TABLE_NAME=#{tableName, jdbcType=VARCHAR}
</select>

<select id="showCreateTable" resultType="java.util.Map" parameterType="java.lang.String">
show create table ${value}
</select>

<update id="dropTable" parameterType="java.lang.String">
drop table IF EXISTS ${value}
</update>

<update id="createNewTable" parameterType="java.lang.String">
${value}
</update>


 (참고로 위의 예제에 ${value} 부분은 MyBatis 의 동적쿼리문을 사용한 부분으로 Parameter Type 을 String 으로 한다면 value 라는 명칭을 사용해야 한다. 내부적으로 String.value 를 이용하기 때문이다. 또한 위의 예시에서 createNewTable 로 매핑된 부분의 ${value} 에는 Create Table 쿼리가 포함되면 된다.)


 다만 한가지 주의할 점은, DML(Data Manipulation Language)가 아닌 위와 같은 DDL(Data Definition Language) 들은 대부분 트랜잭션을 사용하더라도 롤백이 되지 않는다.


몇가지 SQL 구문들은 MySQL 이 암묵적으로 커밋을 하기 때문에 트랜잭션을 감싸더라도 실행하면 롤백이 불가능하다. 트랜잭션이 불가능한 대표적 구문들은 다음과 같다.


CREATE / ALTER / DROP DATABASE

CREATE /ALTER / DROP / RENAME / TRUNCATE TABLE

CREATE / DROP INDEX

CREATE / DROP EVENT

CREATE / DROP FUNCTION

CREATE / DROP PROCEDURE





 MyBatis 란 객체지향 언어인 Java 와 SQL Based 인 관계형 데이터베이스(RDBMS) 사이의 데이터를 다루는 방식의 괴리를 해결하기 위해 만들어진 Persistence Framework 의 일종이다.


 Java 에서 DB와의 Connection 을 위해 제공하는 JDBC 를 Wrapping 한 구조로 되어 있으며, 기존의 JDBC 에 비해 많은 장점들을 갖고 있다.


무엇보다 사용이 간단하고, 60% 정도의 생산성 향상이 있다고 한다.

또한 JDBC 사용시 매번 Query Statement 를 생성하는 구문을 작성해야 했던 것과 다르게 쿼리의 재사용과, 코드와의 분리가 좀 더 수월해졌기 때문에 유지 보수 측면에서도 이점을 갖는다.


 주로 mybatis-config.xml 과 같이 별도의 파일에 환경 설정을 분리시키며, 변수 형태로 DB 연결정보들을 관리한다.

간단한 설정 방법은 다음과 같다.



/* 설정 <pom.xml> */
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>



 Maven 을 사용한다면 위와 같이 먼저 pom.xml 에 MyBatis Dependency 를 기입해주어야 한다. 이후 다음과 같이 프로젝트별로 관리하는 개별 설정 파일에 내용을 기입해주면 된다.



/* 설정 <설정파일.xml> */

//Property 설정 분리
<properties resource="mybatis/config.properties">
<property name="username" value="jinsp"/>
<property name="password" value="epD@kef0"/>
</properties>


//커넥션 풀 사용
<dataSource type="POOLED">
//Database Driver
<property name="driver" value="${driver}"/>
//Database Url
<property name="url" value="${url}"/>
//Database UserName
<property name="username" value="${username}"/>
//Database Password
<property name="password" value="${password}"/>
</dataSource>



 이렇게 설정해준다면 MyBatis 의 SqlSessionFactory 를 통해 Connection 을 연결할 수 있다. MyBatis 의 사용을 위해서는 매퍼 파일(Mapper File) 이라 불리는 Xml 설정이 추가로 필요하다. 이는 다음과 같은 형태로 구성이 되어 있다.




<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="StudentRepository">
<select id="selectStudentList" resultType="student">
SELECT
`id` AS "studentId",
`name` AS "studentName"
FROM
student
</select>
</mapper>



 위의 Mapper 설정에 대한 설명을 간단히 하자면, 설정들이 StudentRepository 라는 @Repository 로 명시된 클래스에 매핑되며, 그 안에 학생들의 리스트를 조회하는 쿼리문인 selectStudentList 를 사용할 수 있게 설정되어있다는 뜻이다. selectStudentList 라는 Id 를 가진 SQL 문은 쿼리문의 결과(ResultType)를 Student 형태의 객체의 형태로 반환하며, 요소가 여러개일 경우 List 형태의 Collection 으로 반환한다.


위와 같이 설정을 하고, 위에 명시된 쿼리의 ID 를 SessionFactory 를 통해 불러와서 실행시켜주면 연동이 간단하게 끝난다.




 Sharding 이란 RDB에서 대량의 데이터를 처리하기 위해 분산 서버에 데이터를 나누어 파티셔닝하는 기술로, 근래에 탄생하는 웹서비스의 경우 필수적으로 고려해야하는 기술이다. 


 샤딩은 DBMS레벨에서 데이터를 나누는 것이 아니라 데이터베이스 자체의 Access Routing 을 분할하기 때문에 Application 레벨에서 처리되어야 하는 문제이다. 최근에는 이를 공통화시키고 그 자체로 서비스화를 위해 미들웨어로 이식하는 추세에 있다.


 샤딩에는 Partition 기법에 따라 주로 쓰이는 몇가지 기법이 있다.


(1) Horizontal Partitioning


 Schema 가 같은 데이터를 두개 이상의 DB에 나눠 처리하는 방법이다. 가장 간단한 방식의 분할 법이고, Partitioning 정책으로 range based 방법을 사용한다면 단순한 구조로 시스템을 구축할 수 있다. 단, 여러 DB에 대해 파티셔닝을 적용 시, 데이터베이스 JOIN 문제나 Consistency, Replication 등 복잡한 문제가 많이 생기게 된다. 따라서 적용시 가능한 DB를 단순하게 설계한다.



(2) Vertical Partitioning


 테이블 별로 서버를 분할하는 방식이다. 예를들어 프로필 관리용, 사진 관리용 서버 등으로 나누어 데이터를 용도에 맞게 분할하며 구현이 간단하고 전체 시스템에 큰 변화를 주지 않아도 된다. 단 서버의 데이터가 점점 거대해지면 추가 샤딩이 필요하므로 구조를 잘 잡아놓아야 한다.



(3) Range Based Partitioning


 하나의 feature 또는 테이블이 점점 거대해지는 경우 서버를 분리한다. 범위에 따라 데이터를 나누기 때문에 단순하지만 데이터를 분할하는 기준이 예측 가능하고 명확해야 한다.



(4) Key / Hash Based Partitioning


 엔티티를 해쉬 함수에 넣어서 나오는 값을 키로 데이터를 샤딩하는 기법이다. Modular 함수가 주로 사용되며 데이터가 균등하게 분포될 수 있도록 해쉬함수를 정해야 한다. 이 방법의 단점은 Scale out 시 해쉬 함수를 변경하는 작업이 매우 비싸다는 것이다.



(5) Directory Based Partitioning


 DB와 별개로 추상화된 룩업테이블을 만들어 샤드 키에 해당하는 데이터를 Cache해서 찾는 식으로 구현된다.



 샤딩 적용시에는 몇가지 고려할 점이 있다.


- 데이터 재분배(Rebalancing) : 서비스 정지 없이 Scale out 이 가능한지를 고려해야 한다.


- 데이터 조인 : Sharding DB 간의 조인이 불가능하므로 역정규화를 감안하여 설계해야 한다. 데이터 중복은 대용량처리에 대한 tradeoff이다.


- Partitioning 기법 : 어떤 식으로 Data를 나눌 건지를 고민해야 한다. 이는 Scalable 한 아키텍처를 위한 중요한 요소이다.


- Global Unique Key : DB간 사용하는 키의 Uniqueness 를 고려해야 한다.


- Compact Table : 테이블의 단위를 가능한 작게 유지해야 한다.





 Primary key(이하 PK)는 한 개 혹은 여러 개의 칼럼으로 테이블 내의 각 행들을 구별하기 위한 목적을 갖고 있다.

 PK는 그 자체만으로 Unique 하며 만약 여러 개의 Column이 PK로 묶여 있다면, 해당 값들의 조합이 반드시 Unique 해지게 된다.

 PK는 NULL 값을 갖을 수 없고(NOT NULL), Unique key라는 특징을 갖게 된다. 단순하게는 NOT NULL & UNIQUE == PK 라고 생각하면 편하다. 물론 좀더 디테일하게 보자면 차이가 있다.


 MySQL에서는 Int 작업이 빠르기 때문에 PK는 Int형으로 지정하는 것이 좋다. 


 Unique Key(Unique index)는 value의 값을 유일하게 만드는 column의 제약으로 PK와는 조금 다르게 NULL값이 가능하며, 역시 여러 개로 묶어서 Combination Index 를 만드는 것이 가능하다.


 * MySQL에서 Key와 Index는 동의어이다. (PRIMARY KEY 가 아니라 Key 가 Index와 동의어이다. 물론 PK 는 Index로 취급되긴 한다.)

 Unique Key 와 PK 의 차이점은, NULL 허용 여부와 의미 상의 차이가 있다. PK 로 지정된 Column 들은 Table 의 Row 를 구분하는 대표 값들이라는 Identity 를 갖지만, Unique Key 는 그보다는 좀더 제약(Constraint) 에 가깝다. 물론 "Unique" 해야 하기 때문에 구분하는 대표값으로 사용해도 무방하지만, PK 처럼 테이블의 대표값라고 취급하는 것은 위험하다.


 MySQL PK 지정 예시. (생성시)


(ex) Create table t(

id int not null, 

name char(10) not null, 

contents text, 

primary key(id, name));


 MySQL PK 추가 예시. (테이블에 추가)


(ex) Alter table 테이블 Add Primary key(칼럼)


 Key 값 조회하는 방법 예시.


(ex) Show Keys from 테이블



 물론 복잡한 DB 쿼리를 다루었던 프로젝트에서는 데이터 무결성을 효율적으로 관리하던 Constraint 를 본적이 있었지만, 경험상 실무에서 Unique Key Constraint 보다는 주로 PK로 값 연결하는 일이 많았다. 

 Unique Key Constraint 는 데이터 무결성에 있어서 좋은 도구이기는 하나... Constraint 도구들이 실 서비스에서도 유용하다고 볼순 없기 때문에 PK 만큼 유용하게 사용되지는 않는 듯 하다.




+ Recent posts