OpenVPN 서버 구축 #1. 개요

OpenVPN 서버 구축 #2. 서버 설치 및 설정

가상사설망(假想私設網) 또는 VPN(영어: virtual private network)은 공중 네트워크를 통해 한 회사나 몇몇 단체가 내용을 바깥 사람에게 드러내지 않고 통신할 목적으로 쓰이는 사설 통신망이다.가상 사설망에서 메시지는 인터넷과 같은 공공망 위에서 표준 프로토콜을 써서 전달되거나, 가상 사설망 서비스 제공자와 고객이 서비스 수준 계약을 맺은 후 서비스 제공자의 사설망을 통해 전달된다.

가상 사설망의 등장배경은 인터넷을 기반으로 한 기업 업무환경의 변화에 기인한다. 즉, 소규모 지역에서 문서만을 전달하던 업무처리 기반에서 하나의 건물 내의 네트워크를 이용한 업무로, 다시 본사와 다수의 지사 관계, 또한 지사는 국내 지사와 국외 지사로 확장되었다. 이들이 하나의 네트워크 구축을 위해 기존 전용선을 사용하는 방법에는 비용을 포함한 여러가지 한계를 가지며, 전용선을 이용해서 네트워크가 구성되었다고 하더라도 네트워크 운영을 자체적으로 하는 것과 새로운 기술들을 도입하는 것 역시 기업의 입장에서는 상당한 부담이 될 수 있다. 또한 기존의 공중 네트워크는 보안과 관련해서는 서비스를 제공하지 않기 때문에 중요한 문서나 데이터를 전달하기에는 부족한 점이 있었다. 이러한 복합적인 이유가 가상 사설망이 등장한 계기가 되었다.1위키백과에서 발췌

왜 VPN이 생겨났는가는 단순하다.
A라는 회사가 있다고 생각해보자. 최첨단 산업을 선도하는 A사는 시간이 흐르면서 회사의 규모도 커지고 직원도 늘어나면서 서울에 본사 뿐 아니라 미국, 중국, 영국 등 세계 각국의 주요 거점에도 지사를 세우게 됐다.

서울 본사만 있을 때는 사내망 관리만 하면 됐지만 미국지사와 중요한 자료를 주고받으려니 일반망으로 데이터를 주고 받자니 중간에 패킷을 가로채거나 하는 공격의 위험이 크고, 서울에서 미국까지 전용선을 설치하자니 너무 비용이 많이 든다.

이러한 상황에서의 보안 요건을 충족하기 위한 것이 바로 Virtual Private Network 되시겠다.
즉, 일반망을 사용하되, 암호화 등의 조치를 통해 본사와 미국지사 사이의 연결이 사설망인 것 처럼 동작하게 하는 것, 그것이 VPN이다.


PPPTP / L2TP / IPSEC / SSL 등의 방식이 있으며, 근래에는 IPSEC, SSL 두 종류로 수렴하는 듯 한다.
가장 많이 쓰이는 IPSEC / SSL 방식 VPN의 차이를 찾자면
– SSL 방식이건 IPSEC이건 모두 암호화방식이나, 터널 개념에 있어서 큰 차이는 없다.

이건 SSL-VPN

– 클라이언트와 대상 망의 VPN 서버와 터널을 맺고 암호화 통신을 한다.

이건 IPSEC

– 양자간 각각의 VPN server를 두고 각 VPN 서버끼리 터널을 맺고 통신을 한다.

SSL 그리고 HTTPS

SSL (Secure Socket Layer)

전송 계층 보안(영어: Transport Layer Security, TLS, 과거 명칭: 보안 소켓 레이어/Secure Sockets Layer, SSL)는 컴퓨터 네트워크에 통신 보안을 제공하기 위해 설계된 암호 규약이다. 그리고 ‘트랜스포트 레이어 보안’이라는 이름은 ‘보안 소켓 레이어’가 표준화 되면서 바뀐 이름이다. 이 규약은 인터넷 같이 TCP/IP 네트워크를 사용하는 통신에 적용되며, 통신 과정에서 전송계층 종단간 보안과 데이터 무결성을 확보해준다. 이 규약은 웹 브라우징, 전자 메일, 인스턴트 메신저, voice-over-IP (VoIP) 같은 응용 부분에 적용되고 있다. 국제 인터넷 표준화 기구(IETF)에 의해 현재 구식(deprecate)으로 간주되어 있다. 최종 갱신은 RFC 5246이고, 최종 갱신 버전은 넷스케이프에서 만든 SSL 표준을 바탕으로 했다. 위키백과 발췌
용어 사용 시 SSL과 TLS를 구분해야 할 필요는 없다. 사실 TLS보다 SSL이 더 입에 잘 붙는다.

먼저 컴퓨터의 암호화에 대해 아주 쉽게 설명하면
컴퓨터는 0과 1만 존재한다 (on, off).
즉 컴퓨터는 숫자만 존재한다.
숫자 1,000이 있다고 가정하면 이 숫자 1,000이 아닌 것처럼 보이게 한다. = 암호화

예를 들어
1,000 X 100 = 10,000
1,000은 내가 암호화 하고 싶은 원본
곱하기는 ‘암호화 알고리즘’
100은 암호화를 위한 ‘키’ 가 되겠다.

여기에서 철수가 영희에게 금고의 비밀번호를 알려주는 상황을 적용해보자.
금고의 비밀번호는 1000이다.
비밀번호는 철수만 알고 있다.
주변에 사람이 많아서 비밀번호를 그냥 말하면 금고의 비밀번호가 노출된다.
보안을 위해 100이라는 숫자를 키로 하여 곱하기 알고리즘으로 암호화한다.
철수는 영희에게 ‘비밀번호는 10000이야. 곱하기 알고리즘으로 암호화 했어’ 라고 말한다.
여기까지가 기본적인 암호화,암호화 데이터 전송 순서가 되겠다.

하지만,
철수가 미리 영희에게 키를 알려줬다면 문제가 없겠지만 만약 영희는 아직 키를 모른다면?
의 경우에 대응하기 위해서 나온 기술이 바로 SSL 되시겠다. (엄밀히 말하면 좀.. 다르지만)

공개키 암호화와 비공개키 암호화 (=비대칭키 암호화와 대칭키 암호화)

개념상 두 종류의 자물쇠가 있다고 생각하면 편하고. 하나는 ‘잠그는 열쇠, 여는 열쇠가 따로 있는 자물쇠’ = A 다른 하나는 ‘잠글 때 열 때 같은 열쇠를 사용하는 자물쇠’ = B. SSL의 중요한 개념은 여기에 있다.

자물쇠 A : 소인수분해를 통해 소수(자기 자신과 1로만 나뉘어지는 수)를 찾아 내는 것이 쉽지 않다는 것에 기인하여 만들어진 알고리즘을 이용한다.11,2,3,5,7,11… 은 소수임을 금방 알아낼 수 있지만 10,000,000,000,000,001이 소수인지는 알아내기 쉽지 않다. 아직 특정한 수가 소수인지 아닌지 알아내는 방법은 없다(고한다. 난 산수 싫다. 어렵다.) 그래서 느리다(고 한다.)
잠그는 열쇠와, 여는 열쇠가 구분 되어있다. 열쇠 하나는 잠그는 것만 가능하고 하나는 여는 것만 가능하다.
잠글 때 쓰는 열쇠와 열 때 쓰는 열쇠가 다르다 = 비대칭 키
암호화,복호화 하는데 시간이 많이 걸린다.

자물쇠 B :열쇠 하나만 있으면 열고 잠그는 것이 가능하다.
잠글 때 쓰는 열쇠와 열 때 쓰는 열쇠가 같다 = 대칭 키
암호화, 복호화 하는데 시간이 덜 걸린다. (비대칭키 암호화 알고리즘에 비해)

위에서부터 순서대로 사건이 발생한다.
철수와 영희의 모든 대화는 가운데 도둑이 들을 수 있다.

위와 같은 절차로 Kk를 주고 받는 것이 ‘키 교환’ 알고리즘이 되겠다. (개념상으로 이렇다는 것만 이해하자. 실제 키를 주고 받는데엔 다양한 방법이 존재한다. DH, RSA 등이 포함되면 키를 교환하기 위한 수단이구나 생각하면 된다.)

HTTPS
언뜻 보면 완벽해 보이지만 여기에 큰 맹점이 하나 있다. 바로 도둑이 철수인 척 하여 중간에서 데이터를 가로채는 경우이다.
1. 철수에게서 받은 K1을 받는다.
2. K1#을 만들어 영희에게 전달한다
3. 영희는 K1#으로 Kk를 암호화 하여 도둑에게 전달한다.
4. 도둑은 K2#으로 복호화하여 Kk를 획득한다.
5. K1으로 Kk를 암호화 하여 철수에게 전달한다.
이후부터는 Kk로 암호화한 데이터가 오가므로 쉽게 복호화 할 수 있다.

즉, 철수와 영희는 실제 상대방이 누구인지 확인할 수 없다는 사실이다.
우리가 사용하는 SSL-HTTPS는 이를 보완하기 위한 제 3자 증명 과정이 추가된다.

TPC-H #1 . 준비

The TPC Benchmark™H (TPC-H) is a decision support benchmark. It consists of a suite of business oriented ad-hoc queries and concurrent data modifications.
라고 한다.
동일한 구조 동일한 데이터를 가진 테이블들을 대상으로 쿼리를 실행하여 하드웨어 성능을 비교할 때 사용한다. 1..고 한다. TPC 홈페이지에 가면 다양한 시험 방법을 제공한다.

설치
여타 소프트웨어의 설치와는 다르게 DBMS에 맞는 테이블 생성 쿼리와 샘플 데이터를 만드는 툴을 이용해 DDL과 샘플 데이터를 생성하는 것이 목적이다.
TPC 홈페이지에서 필요한 도구를 다운로드한다. 2예제는 tpc-h를 기준으로 한다. 계정,권한 관련 제한이 없으므로 아무 계정으로 다운로드 해서 진행 해도 무방하다.

PostgresQL에 테이블을 생성하고 데이터를 넣을 것이다.

dbgen(샘플데이터 생성기) 컴파일
압축 해제

[root@tpc tpc]$ ls
tpc-ds-tool.zip  tpc-h-tool.zip  v2.13.0rc1
[root@tpc tpc]# unzip tpc-h-tool.zip
...생략...
  inflating: 2.18.0_rc2/ref_data/300/supplier.tbl.19998
  inflating: 2.18.0_rc2/ref_data/300/supplier.tbl.29997
  inflating: 2.18.0_rc2/ref_data/300/supplier.tbl.30000
  inflating: 2.18.0_rc2/ref_data/300/supplier.tbl.9999
  inflating: 2.18.0_rc2/specification.docx
  inflating: 2.18.0_rc2/specification.pdf
[root@tpc tpc]$ ls
2.18.0_rc2  tpc-ds-tool.zip  tpc-h-tool.zip  v2.13.0rc1
[root@tpc tpc]$ cd 2.18.0_rc2
[root@tpc tpc]$ ls
EULA.txt  dbgen  dev-tools  ref_data  specification.docx  specification.pdf
[root@tpc 2.18.0_rc2]$ cd dbgen
[root@tpc 2.18.0_rc2]$ ls
BUGS           README   bcd2.h      check_answers    dbgen.dsp  dss.ddl  dsstypes.h      permute.c  qgen.c       reference  rnd.h    shared.h      text.c    tpch.sln           variants
HISTORY        answers  bm_utils.c  column_split.sh  dists.dss  dss.h    load_stub.c     permute.h  qgen.vcproj  release.h  rng64.c  speed_seed.c  tpcd.h    tpch.vcproj        varsub.c
PORTING.NOTES  bcd2.c   build.c     config.h         driver.c   dss.ri   makefile.suite  print.c    queries      rnd.c      rng64.h  tests         tpch.dsw  update_release.sh

dbgen 컴파일을 위한 설정 파일 수정

 # makefile 생성
[root@tpc dbgen]$ cp    makefile.suite      makefile
[root@tpc dbgen]$ vi     makefile
 # 컴파일러,  대상 DBMS종류, 시스템 종류, workload 정보를 변경한다.
 # CC = , DATABASE = , MACHINE = , WORKLOAD = 항목을 찾는다.
 # 리눅스에 설치된 ORACLE 을 기준으로 다음과 같이 변경. (아래 주석 참고)
CC      = gcc
DATABASE= ORACLE
MACHINE = LINUX
WORKLOAD = TPCH
# Current values for DATABASE are: INFORMIX, DB2, TDAT (Teradata)
#                                  SQLSERVER, SYBASE, ORACLE, VECTORWISE
# Current values for MACHINE are:  ATT, DOS, HP, IBM, ICL, MVS,
#                                  SGI, SUN, U2200, VMS, LINUX, WIN32
# Current values for WORKLOAD are:  TPCH

컴파일 및 확인
dbgen 파일이 생성되면 정상적으로 컴파일이 된 것이다.

[root@tpc dbgen]$  make
gcc -g -DDBNAME=\"dss\" -DLINUX -DORACLE -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o build.o build.c
gcc -g -DDBNAME=\"dss\" -DLINUX -DORACLE -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o driver.o driver.c
gcc -g -DDBNAME=\"dss\" -DLINUX -DORACLE -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o bm_utils.o bm_utils.c
gcc -g -DDBNAME=\"dss\" -DLINUX -DORACLE -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o rnd.o rnd.c
gcc -g -DDBNAME=\"dss\" -DLINUX -DORACLE -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o print.o print.c
gcc -g -DDBNAME=\"dss\" -DLINUX -DORACLE -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o load_stub.o load_stub.c
gcc -g -DDBNAME=\"dss\" -DLINUX -DORACLE -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o bcd2.o bcd2.c
gcc -g -DDBNAME=\"dss\" -DLINUX -DORACLE -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o speed_seed.o speed_seed.c
gcc -g -DDBNAME=\"dss\" -DLINUX -DORACLE -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o text.o text.c
gcc -g -DDBNAME=\"dss\" -DLINUX -DORACLE -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o permute.o permute.c
gcc -g -DDBNAME=\"dss\" -DLINUX -DORACLE -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o rng64.o rng64.c
gcc -g -DDBNAME=\"dss\" -DLINUX -DORACLE -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64  -O -o dbgen build.o driver.o bm_utils.o rnd.o print.o load_stub.o bcd2.o speed_seed.o text.o permute.o rng64.o -lm
gcc -g -DDBNAME=\"dss\" -DLINUX -DORACLE -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o qgen.o qgen.c
gcc -g -DDBNAME=\"dss\" -DLINUX -DORACLE -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o varsub.o varsub.c
gcc -g -DDBNAME=\"dss\" -DLINUX -DORACLE -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64  -O -o qgen build.o bm_utils.o qgen.o rnd.o varsub.o text.o bcd2.o permute.o speed_seed.o rng64.o -lm
[root@tpc dbgen]$  ll
total 920
...중략...
-rwxr-xr-x 1 root root 111910 Aug  2 13:01 dbgen
-rw-r--r-- 1 root root   5154 Dec  5  2018 dbgen.dsp
...중략...
-rwxr-xr-x 1 root root 103060 Aug  2 13:01 qgen
-rw-r--r-- 1 root root  14404 Dec  5  2018 qgen.c
-rw-r--r-- 1 root root  48984 Aug  2 13:01 qgen.o
-rw-r--r-- 1 root root   4916 Dec  5  2018 qgen.vcproj
drwxr-xr-x 2 root root   4096 Feb 18 12:03 queries
-rw-r--r-- 1 root root  17617 Dec  5  2018 README

※ TPC-H는 정확하게 PostgresQL용 쿼리를 제공하지 않는다. ORACLE용 쿼리와 데이터를 생성하고 이를 이용해 PostgresQL에 데이터를 넣을 것이다.

데이터 및 테스트 쿼리 생성
dbgen을 실행하면 실험용 쿼리와 데이터가 자동으로 생성된다.

# 데이터 및 쿼리 생성
[root@tpc dbgen]$  ./dbgen
TPC-H Population Generator (Version 3.0.0)
Copyright Transaction Processing Performance Council 1994 - 2010
 # 편의를 위해 쿼리파일과 샘플 데이터를 한곳으로 옮긴다.
[root@tpc dbgen]# mkdir data
[root@tpc dbgen]# cp *.ddl data/
[root@tpc dbgen]# cp *.tbl data/
# 확인 - 중간에 dss.ddl 파일에 테이블 생성 스크립트가 존재한다.
[root@tpc dbgen]$ ll data
total 1074924
-rw-r--r-- 1 root root  24346144 Aug  2 13:07 customer.tbl
-rw-r--r-- 1 root root      3814 Dec  5  2018 dss.ddl
-rw-r--r-- 1 root root 759863287 Aug  2 13:07 lineitem.tbl
-rw-r--r-- 1 root root      2224 Aug  2 13:07 nation.tbl
-rw-r--r-- 1 root root 171952161 Aug  2 13:07 orders.tbl
-rw-r--r-- 1 root root 118984616 Aug  2 13:07 partsupp.tbl
-rw-r--r-- 1 root root  24135125 Aug  2 13:07 part.tbl
-rw-r--r-- 1 root root       389 Aug  2 13:07 region.tbl
-rw-r--r-- 1 root root   1409184 Aug  2 13:07 supplier.tbl
[root@tpc dbgen]$ ll queries/
total 88
-rw-r--r-- 1 root root  646 Dec  5  2018 10.sql
-rw-r--r-- 1 root root  631 Dec  5  2018 11.sql
-rw-r--r-- 1 root root  720 Dec  5  2018 12.sql
-rw-r--r-- 1 root root  470 Dec  5  2018 13.sql
-rw-r--r-- 1 root root  442 Dec  5  2018 14.sql
-rw-r--r-- 1 root root  641 Dec  5  2018 15.sql
-rw-r--r-- 1 root root  609 Dec  5  2018 16.sql
-rw-r--r-- 1 root root  411 Dec  5  2018 17.sql
-rw-r--r-- 1 root root  581 Dec  5  2018 18.sql
-rw-r--r-- 1 root root 1090 Dec  5  2018 19.sql
-rw-r--r-- 1 root root  666 Dec  5  2018 1.sql
-rw-r--r-- 1 root root  711 Dec  5  2018 20.sql
-rw-r--r-- 1 root root  804 Dec  5  2018 21.sql
-rw-r--r-- 1 root root  797 Dec  5  2018 22.sql
-rw-r--r-- 1 root root  815 Dec  5  2018 2.sql
-rw-r--r-- 1 root root  518 Dec  5  2018 3.sql
-rw-r--r-- 1 root root  474 Dec  5  2018 4.sql
-rw-r--r-- 1 root root  605 Dec  5  2018 5.sql
-rw-r--r-- 1 root root  363 Dec  5  2018 6.sql
-rw-r--r-- 1 root root  926 Dec  5  2018 7.sql
-rw-r--r-- 1 root root  900 Dec  5  2018 8.sql
-rw-r--r-- 1 root root  741 Dec  5  2018 9.sql

테이블 생성

PostgresQL은 텍스트파일3i.e. csv 파일을 import 할 때 문자열 끝에 구분자가 있으면 컬럼이 하나 더 있는 것으로 인식한다. 따라서 이를 위한 dummy column 을 추가한다.

-- 더미 컬럼에는 데이터가 들어가지 않는다. 따라서 붙여넣기 하다가 not null 도 따라 붙여 넣지 않도록 주의한다.

CREATE TABLE public.NATION  ( N_NATIONKEY  INTEGER NOT NULL,
                            N_NAME       CHAR(25) NOT NULL,
                            N_REGIONKEY  INTEGER NOT NULL,
                            N_COMMENT    VARCHAR(152),
                            N_DUMMY   VARCHAR(1));
                           
CREATE TABLE public.REGION  ( R_REGIONKEY  INTEGER NOT NULL,
                            R_NAME       CHAR(25) NOT NULL,
                            R_COMMENT    VARCHAR(152),
                            R_DUMMY VARCHAR(1));

CREATE TABLE public.PART  ( P_PARTKEY     INTEGER NOT NULL,
                          P_NAME        VARCHAR(55) NOT NULL,
                          P_MFGR        CHAR(25) NOT NULL,
                          P_BRAND       CHAR(10) NOT NULL,
                          P_TYPE        VARCHAR(25) NOT NULL,
                          P_SIZE        INTEGER NOT NULL,
                          P_CONTAINER   CHAR(10) NOT NULL,
                          P_RETAILPRICE DECIMAL(15,2) NOT NULL,
                          P_COMMENT     VARCHAR(23) NOT null,
                          P_DUMMY VARCHAR(1));

CREATE TABLE public.SUPPLIER ( S_SUPPKEY     INTEGER NOT NULL,
                             S_NAME        CHAR(25) NOT NULL,
                             S_ADDRESS     VARCHAR(40) NOT NULL,
                             S_NATIONKEY   INTEGER NOT NULL,
                             S_PHONE       CHAR(15) NOT NULL,
                             S_ACCTBAL     DECIMAL(15,2) NOT NULL,
                             S_COMMENT     VARCHAR(101) NOT NULL,
                             S_DUMMY    VARCHAR(1));

CREATE TABLE public.PARTSUPP ( PS_PARTKEY     INTEGER NOT NULL,
                             PS_SUPPKEY     INTEGER NOT NULL,
                             PS_AVAILQTY    INTEGER NOT NULL,
                             PS_SUPPLYCOST  DECIMAL(15,2)  NOT NULL,
                             PS_COMMENT     VARCHAR(199) NOT NULL, );

CREATE TABLE public.CUSTOMER ( C_CUSTKEY     INTEGER NOT NULL,
                             C_NAME        VARCHAR(25) NOT NULL,
                             C_ADDRESS     VARCHAR(40) NOT NULL,
                             C_NATIONKEY   INTEGER NOT NULL,
                             C_PHONE       CHAR(15) NOT NULL,
                             C_ACCTBAL     DECIMAL(15,2)   NOT NULL,
                             C_MKTSEGMENT  CHAR(10) NOT NULL,
                             C_COMMENT     VARCHAR(117) NOT NULL,
                             C_DUMMY VARCHAR(1));

CREATE TABLE public.ORDERS  ( O_ORDERKEY       INTEGER NOT NULL,
                           O_CUSTKEY        INTEGER NOT NULL,
                           O_ORDERSTATUS    CHAR(1) NOT NULL,
                           O_TOTALPRICE     DECIMAL(15,2) NOT NULL,
                           O_ORDERDATE      DATE NOT NULL,
                           O_ORDERPRIORITY  CHAR(15) NOT NULL,
                           O_CLERK          CHAR(15) NOT NULL,
                           O_SHIPPRIORITY   INTEGER NOT NULL,
                           O_COMMENT        VARCHAR(79) NOT NULL,
                           O_DUMMY VARCHAR(1));

CREATE TABLE public.LINEITEM ( L_ORDERKEY    INTEGER NOT NULL,
                             L_PARTKEY     INTEGER NOT NULL,
                             L_SUPPKEY     INTEGER NOT NULL,
                             L_LINENUMBER  INTEGER NOT NULL,
                             L_QUANTITY    DECIMAL(15,2) NOT NULL,
                             L_EXTENDEDPRICE  DECIMAL(15,2) NOT NULL,
                             L_DISCOUNT    DECIMAL(15,2) NOT NULL,
                             L_TAX         DECIMAL(15,2) NOT NULL,
                             L_RETURNFLAG  CHAR(1) NOT NULL,
                             L_LINESTATUS  CHAR(1) NOT NULL,
                             L_SHIPDATE    DATE NOT NULL,
                             L_COMMITDATE  DATE NOT NULL,
                             L_RECEIPTDATE DATE NOT NULL,
                             L_SHIPINSTRUCT CHAR(25) NOT NULL,
                             L_SHIPMODE     CHAR(10) NOT NULL,
                             L_COMMENT      VARCHAR(44) NOT NULL,
                             L_DUMMY VARCHAR(1));

데이터 입력

※ 테이블 명, 컬럼명 등은 대소문자 구분을 하지 않지만 소스 파일 명 및 경로는 대소문자를 구분하므로 주의한다.

COPY public.nation(N_NATIONKEY,N_NAME,N_REGIONKEY,N_COMMENT,N_dummy)
FROM '/home/tpc/2.18.0_rc2/dbgen/sample/nation.tbl'
DELIMITER '|'
;

COPY public.region(R_REGIONKEY,R_NAME,R_COMMENT,R_DUMMY)
FROM '/home/tpc/2.18.0_rc2/dbgen/sample/region.tbl'
DELIMITER '|'
;

COPY public.part(P_PARTKEY,P_NAME,P_MFGR,P_BRAND,P_TYPE,P_SIZE,P_CONTAINER,P_RETAILPRICE,P_COMMENT,P_DUMMY VARCHAR)
FROM '/home/tpc/2.18.0_rc2/dbgen/sample/part.tbl'
DELIMITER '|'
;

COPY public.supplier(S_SUPPKEY,S_NAME,S_ADDRESS,S_NATIONKEY,S_PHONE,S_ACCTBAL,S_COMMENT)
FROM '/home/tpc/2.18.0_rc2/dbgen/sample/supplier.tbl'
DELIMITER '|'
;

COPY public.partsupp(PS_PARTKEY,PS_SUPPKEY,PS_AVAILQTY,PS_SUPPLYCOST,PS_COMMENT,PS_DUMMY)
FROM '/home/tpc/2.18.0_rc2/dbgen/sample/partsupp.tbl'
DELIMITER '|'
;

COPY public.customer(C_CUSTKEY,C_NAME,C_ADDRESS,C_NATIONKEY,C_PHONE,C_ACCTBAL,C_MKTSEGMENT,C_COMMENT,C_dummy)
FROM '/home/tpc/2.18.0_rc2/dbgen/sample/customerp.tbl'
DELIMITER '|'
;
                           
COPY public.orders(O_ORDERKEY,O_CUSTKEY,O_ORDERSTATUS,O_TOTALPRICE,O_ORDERDATE,O_ORDERPRIORITY,O_CLERK,O_SHIPPRIORITY,O_COMMENT,O_DUMMY)
FROM '/home/tpc/2.18.0_rc2/dbgen/sample/orders.tbl'
DELIMITER '|'
;

COPY public.lineitem(L_ORDERKEY,L_PARTKEY,L_SUPPKEY,L_LINENUMBER,L_QUANTITY,L_EXTENDEDPRICE,L_DISCOUNT,L_TAX,L_RETURNFLAG,L_LINESTATUS,L_SHIPDATE,L_COMMITDATE,L_RECEIPTDATE,L_SHIPINSTRUCT,L_SHIPMODE,L_COMMENT,L_DUMMY)
FROM '/home/tpc/2.18.0_rc2/dbgen/sample/lineitem.tbl'
DELIMITER '|'
;

확인

 # 실행 예
 # PostgresQL import 문법이므로 기억하자
tpc=$ COPY public.customer(c_custkey,c_name,c_address,c_nationkey,c_phone,c_acctbal,c_mktsegment,c_comment,c_dummy)
tpc-$ FROM '/home/tpc/2.18.0_rc2/dbgen/sample/region.tbl'
tpc-$ DELIMITER '|'
tpc-$ ;
COPY 150000
tpc=$
 # 확인
tpc=$ select count(*) from public.customer;
 count
--------
 150000
(1개 행)

tpc=$ select * from public.customer limit 1;
 c_custkey |       c_name       |     c_address     | c_nationkey |     c_phone     | c_acctbal | c_mktsegment |                           c_comment                            | c_dummy
-----------+--------------------+-------------------+-------------+-----------------+-----------+--------------+----------------------------------------------------------------+---------
         1 | Customer#000000001 | IVhzIApeRb ot,c,E |          15 | 25-989-741-2988 |    711.56 | BUILDING     | to the even, regular platelets. regular, ironic epitaphs nag e |
(1개 행)

tpc=$ \dt
       릴레이션(relation) 목록
 스키마 |   이름   |  종류  | 소유주
--------+----------+--------+--------
 public | customer | 테이블 | tpc
 public | lineitem | 테이블 | tpc
 public | nation   | 테이블 | tpc
 public | orders   | 테이블 | tpc
 public | part     | 테이블 | tpc
 public | partsupp | 테이블 | tpc
 public | region   | 테이블 | tpc
 public | supplier | 테이블 | tpc
(8개 행)

tpc=$

PostgresQL #.2 설정

인터페이스 변경

이전 포스트에서 구동 한 PostgresQL서버는 기본 값 loopbak(127.0.0.1) 인터페이스로 구동 되었다. 외부 연결을 위해서는 서비스 리슨 인터페이스를 변경 해 줘야 한다.
Listen 인터페이스 관련 설정은 postgresql.conf 파일에 정의 돼 있다. 이전 포스트의 내용대로 설치 했을 경우 설정 파일은 /var/lib/pgsql/12/data 아래에 존재한다. 1설치 할 때의 조건에 따라 /etc/postgresql/version 디렉토리 아래에 존재할 수 도 있다.

[postgres@centos7:/home/]$  vi /var/lib/pgsql/12/data/postgresql.conf
 
 # 아래 "listen_addresses"와 "port" 값을 변경해 주면 되는데 주석처리가 돼 있으므로 파일 끝에 새 값을 삽입한다.
      ... 중략...
#------------------------------------------------------------------------------
# CONNECTIONS AND AUTHENTICATION
#------------------------------------------------------------------------------
# - Connection Settings -
#listen_addresses = 'localhost'         # what IP address(es) to listen on;
                                        # comma-separated list of addresses;
                                        # defaults to 'localhost'; use '*' for all
                                        # (change requires restart)
#port = 5432                            # (change requires restart)
max_connections = 100                   # (change requires restart)
#superuser_reserved_connections = 3     # (change requires restart)
#unix_socket_directories = '/var/run/postgresql, /tmp'  # comma-separated list of directories
                                        # (change requires restart)
#unix_socket_group = ''                 # (change requires restart)
#unix_socket_permissions = 0777         # begin with 0 to use octal notation
                                        # (change requires restart)
#bonjour = off                          # advertise server via Bonjour
                                        # (change requires restart)
#bonjour_name = ''                      # defaults to the computer name
                                        # (change requires restart)

# - TCP settings -
# see "man 7 tcp" for details

#tcp_keepalives_idle = 0                # TCP_KEEPIDLE, in seconds;
                                        # 0 selects the system default
#tcp_keepalives_interval = 0            # TCP_KEEPINTVL, in seconds;
                                        # 0 selects the system default
#tcp_keepalives_count = 0               # TCP_KEEPCNT;
                                        # 0 selects the system default
    ....중략...

 # 여기부터 파일 끝에 삽입한다.
listen_addresses = '0.0.0.0'
 # 인터페이스가 여러개일 경우 0.0.0.0을 입력하면 모든 인터페이스가 연결을 받아들이고
 # 특정 IP를 입력하면 지정한 IP로만 연결이 가능한다.
port = 5432                         

인증 방법 설정

 # 패스워드 인증을을 통한 접속 허용을 위한 설정
[postgres@centos7:/home/]$  vi /var/lib/pgsql/12/data/pg_hba.conf
 # 파일의 끝에 아래를 붙여넣기 한다.

host    all             all             0.0.0.0/0               md5
#호스트를 기준으로 모든 계정을 이용해 모든 IP에서 들어오는 연결에 대해 패스워드 인증을 허용하는 설정이다.
 #인터페이스 관련 설정을 변경할 경우 재기동이 필요하다.
[postgres@centos7:/home/]$  /usr/pgsql-12/bin/pg_ctl -D /var/lib/pgsql/12/data -l /var/lib/pgsql/12/data/pgsql.log stop
[postgres@centos7:/home/]$  /usr/pgsql-12/bin/pg_ctl -D /var/lib/pgsql/12/data -l /var/lib/pgsql/12/data/pgsql.log start

계정 생성

 # 생성하는 계정에 관리자 권한을 부여할 때
[postgres@centos7:/home/]$   /usr/pgsql-12/bin/createuser psqluser --interactive
createuser dataware --interactive
새 롤을 superuser 권한으로 지정할까요? (y/n) y
 # 관리자 권한을 부여하지 않을 때.
[postgres@centos7:/home/]$   /usr/pgsql-12/bin/createuser psqluser --interactive
새 롤을 superuser 권한으로 지정할까요? (y/n) n
이 새 롤에게 데이터베이스를 만들 수 있는 권할을 줄까요? (y/n) y
이 새 롤에게 또 다른 롤을 만들 수 있는 권한을 줄까요? (y/n) y
 # SQL을 이용한 사용자 생성
[postgres@centos7:/home/]$   /usr/pgsql-12/bin/psql
psql (12.4)
도움말을 보려면 "help"를 입력하십시오.

postgres=# CREATE USER datauser WITH ENCRYPTED PASSWORD 'password';
CREATE ROLE
postgres=#

데이터 베이스 생성

[postgres@centos7:/home/]$   /usr/pgsql-12/bin/psql
psql (12.4)
도움말을 보려면 "help"를 입력하십시오.

postgres=# CREATE DATABASE data OWNER data ENCODING 'utf-8';
CREATE ROLE
postgres=#

접속 확인

 # postgres 가 아닌 다른 계정으로 시도해본다. 원격지에서도 가능하다.
root@centos7:/home/]#   psql -U dataware -W -h localhost

다음과 같이 입력을 쉘이 변하면 정상 구동 중인 상태

암호:
psql (12.4)
도움말을 보려면 "help"를 입력하십시오.

postgres=# select * from pg_tables;
     schemaname     |        tablename        | tableowner | tablespace | hasindexes | hasrules | hastriggers | rowsecurity
--------------------+-------------------------+------------+------------+------------+----------+-------------+-------------
 pg_catalog         | pg_statistic            | postgres   |            | t          | f        | f           | f
 pg_catalog         | pg_type                 | postgres   |            | t          | f        | f           | f
 pg_catalog         | pg_foreign_server       | postgres   |            | t          | f        | f           | f
 pg_catalog         | pg_authid               | postgres   | pg_global  | t          | f        | f           | f
 pg_catalog         | pg_statistic_ext_data   | postgres   |            | t          | f        | f           | f
 pg_catalog         | pg_user_mapping         | postgres   |            | t          | f        | f           | f
 pg_catalog         | pg_subscription         | postgres   | pg_global  | t          | f        | f           | f
 pg_catalog         | pg_attribute            | postgres   |            | t          | f        | f           | f
 pg_catalog         | pg_proc                 | postgres   |            | t          | f        | f           | f
 pg_catalog         | pg_class                | postgres   |            | t          | f        | f           | f
... 중략...
 information_schema | sql_sizing_profiles     | postgres   |            | f          | f        | f           | f
(70개 행)

PostgresQL #.1 설치 및 구동

개요

PostgreSQL은 확장 가능성 및 표준 준수를 강조하는 객체-관계형 데이터베이스 관리 시스템(ORDBMS)의 하나이다. BSD 허가권으로 배포되며 오픈소스 개발자 및 관련 회사들이 개발에 참여하고 있다. 데이터베이스 서버로서 주요 기능은 데이터를 안전하게 저장하고 다른 응용 소프트웨어로부터의 요청에 응답할 때 데이터를 반환하는 것이이다. 소규모의 단일 머신 애플리케이션에서부터 수많은 동시 접속 사용자가 있는 대형의 인터넷 애플리케이션(또는 데이터 웨어하우스용)에 이르기까지 여러 부하를 관리할 수 있으며 macOS 서버의 경우 PostgreSQL은 기본 데이터베이스이다. 마이크로소프트 윈도우, 리눅스(대부분의 배포판에서 제공됨)용으로도 이용 가능하다. PostgresQL의 전신은 Ingres DB로 실제 프로젝트의 공식 명칭은 “post-Ingres” 데이터베이스이다.

설치

Postgresql 사이트에서 yum 리포지터리 RPM을 다운로드 받을 수 있다.

이렇게 제공된다. 아래 텍스트를 복사-붙여넣기 하여 설치하면 된다.
 # repository RPM 설치
 # 설치하면 postgresql repo 파일이 /etc/yum.repos.d 아래 생성된다.
[root@centos7:/root/]# yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
 # PostgresQL 설치
[root@centos7:/root/]# yum install -y postgresql12-server
 
 # 이렇게 설치 해도 된다.
[root@centos7:/root/]# yum install -y postgresql12-*

초기화
initdb를 이용해 데이터 디렉토리 생성 및 지정이 필요하다.
postgresql 서버를 설치하면 postgres 계정이 자동으로 생성되고 DBMS의 최고 권한은 이 postgres 계정이 가지게 된다. 서버 프로세스의 구동부터 모든 작업이 postgres 계정으로 진행되어야 하므로 디렉토리 생성등을 할 경우 postgres 계정에 모든 권한을 부여해야 한다.

 # DB 초기화 등 작업

 # 초기화 :  /var/lib/pgsql/12/data 가 데이터 디렉토리로 '자동'지정된다.
[postgres@centos7:/home/]$ /usr/pgsql-12/bin/initdb 
이 데이터베이스 시스템에서 만들어지는 파일들은 그 소유주가 "postgres" id로
지정될 것입니다. 또한 이 사용자는 서버 프로세스의 소유주가 됩니다.

데이터베이스 클러스터는 "ko_KR.UTF-8" 로케일으로 초기화될 것입니다.
기본 데이터베이스 인코딩은 "UTF8" 인코딩으로 설정되었습니다.
initdb: "ko_KR.UTF-8" 로케일에 알맞은 전문검색 설정을 찾을 수 없음
기본 텍스트 검색 구성이 "simple"(으)로 설정됩니다.

자료 페이지 체크섬 기능 사용 하지 않음

이미 있는 /var/lib/pgsql/12/data 디렉터리의 액세스 권한을 고치는 중 ...완료
하위 디렉터리 만드는 중 ...완료
사용할 동적 공유 메모리 관리방식을 선택하는 중 ... posix
max_connections 초기값을 선택하는 중 ...100
기본 shared_buffers를 선택하는 중... 128MB
기본 지역 시간대를 선택 중 ... Asia/Seoul
환경설정 파일을 만드는 중 ...완료
부트스트랩 스크립트 실행 중 ... 완료
부트스트랩 다음 초기화 작업 중 ... 완료
자료를 디스크에 동기화 하는 중 ... 완료

initdb: 경고: 로컬 접속용 "trust" 인증을 설정 함
이 값을 바꾸려면, pg_hba.conf 파일을 수정하든지,
다음번 initdb 명령을 사용할 때, -A 옵션 또는 --auth-local,
--auth-host 옵션을 사용해서 인증 방법을 지정할 수 있습니다.

작업완료. 이제 다음 명령을 이용해서 서버를 가동 할 수 있습니다:

    ./pg_ctl -D /var/lib/pgsql/12/data -l 로그파일 start
# 초기화 : -pgdata= 로 지정한 디렉토리가 지정된다. 
 # 이경우 지정한 디렉토리의 소유자는 postgres이어야 하고 모든 권한을 가져야 한다.
[root@centos7:/home/]# mkdir /home/postgres
[root@centos7:/home/]# chown -R postgres /home/postgres
 # 쉘에 주의하자 여기까지는 root 이다.
[postgres@centos7:/home/]$ mkdir /home/postgres/data
[postgres@centos7:/home/]$ /usr/pgsql-12/bin/initdb  --pgdata=/home/postgres/data

/usr/pgsql-12/bin/postgresql-12-setup initdb
systemctl enable postgresql-12
systemctl start postgresql-12

구동
initdb 작업 결과의 명령대로 구동하면 된다.

[postgres@centos7:/home/]$ /usr/pgsql-12/bin//pg_ctl -D /var/lib/pgsql/12/data -l /var/lib/pgsql/12/data/pgsql.log start
서버를 시작하기 위해 기다리는 중.... 완료
서버 시작됨

확인

[root@host0 bin]# netstat -nltp |grep postgres
tcp        0      0 127.0.0.1:5432          0.0.0.0:*               LISTEN      96383/postgres

CentOS swap 영역 해제하기

swap 의 사전적 의미. (daum 사전)

개요

Linux의 swap 메모리, swap 영역은 정확히 사전적 의미그대로의 영역을 말한다.
(윈도우는 가상 메모리)

CPU(Cache) – RAM – HDD (혹은 SSD를 포함하는 모든스토리지) 가 있는 컴퓨터는
사용자가 특정한 프로그램을 실행하면
1. HDD에서 필요한 데이터를 읽어서
2. RAM에 일정량을 저장하고
3. 다시 CPU의 Cache 메모리에 일정량을 저장하고
4. CPU에서 연산을 하고
5. 결과를 반환한다.


보통은 위 5단계에서 아무런 문제가 일어나지 않지만 요즘 게임을 하거나, 사진을 찍어서 편집을 하고 하다보면 메모리(RAM) 사용량이 늘어나는 것을 볼 수 있다.

예컨대 RAM이 4GB인데 동영상 편집을 할 때 동영상의 크기가 8GB를 넘어간다면?

바로 이 때 Paging(단편화1 복잡하게 생각 할 필요 없다. 책을 한권 램에 올려야 하는데 램의 크기가 작아서 페이지를 떼어서 올리는 것이라고 생각하면 된다. 우리가 실행하는 게임이건 포토샵이건 다 매 한가지다.) 이라는 작업이 일어나고 swapping 이 필요해 진다.

일단 동양상 편집을 위해 4GB램의 PC에서 8GB짜리 동영상을 로드하게 되면
1. 우선 HDD에 있는 8GB의 데이터 중 4GB의 데이터가 램으로 이동한다.
2. 사용자가 현재 램에 있는 4GB의 동영상 편집을 수행한다.

그런데 이 때 현재 램에 있는 4GB 말고 나머지 반쪽의 내용을 불러와야 한다면?
1. 현재 4GB의 동영상을 HDD의 스왑 파티션으로 이동한다. 2여기서 램에 있는 내용을 삭제 하지 않는 이유는 사용자가 아직 기존에 램에 있던 4GB의 데이터의 작업을 완료하지 않았기 때문이다.
2. HDD에 남아있던 나머지 뒤쪽 4GB를 램에 올린다.
3. 다시 편집 작업을 한다.

그래서 보통 물리 메모리(RAM)의 1배~2배 정도로 설정을 하는데 익히 알고 있다시피 HDD건, SSD건 RAM보다 느린데다가, swap 되는 데이터의 크기 두배3RAM에 있는 데이터를 읽어서, swap에 쓰고 다시 HDD의 데이터를 읽어서 RAM에 올려야 하므로swap으로 만큼 읽고 쓰기가 일어나므로 swapping 이 잦아지면 작업 지연이 생길 수 밖에 없다. 4지금이야 대부분의 PC에 SSD가 달려있어서 잘 못느끼지만 HDD가 주류이던 시절 게임을 하다 지역 이동을 하거나 할 때 본체의 빨간불이 깜빡이며 열심히 HDD가 돌아가고 화면이 멈춰있거나 느려지거나.. 경험 했을 것이다.

swap 영역 해제

 # 현재 swap 정보 확인
[root@centos7:~]# free -h
              total        used        free      shared  buff/cache   available
Mem:            62G        5.5G         54G        264M        2.9G         56G
Swap:           31G          0B         31G

[root@centos7:~]# blkid
/dev/sda1: UUID="d8888888-80c0-4156-8b73-6b5323dd2c01" TYPE="xfs"
/dev/sda2: UUID="p22222-84DI-Hvny-RZ7Z-FbHq-QBq2-tTl5yK" TYPE="LVM2_member"
/dev/sdb1: UUID="45555555-0ca0-4b99-86b5-33e45689fc10" TYPE="xfs"
/dev/mapper/centos-root: UUID="5999999-877a-4fe9-a464-5376cb476310" TYPE="xfs"
/dev/mapper/centos-swap: UUID="2333333-b2d1-4f58-9123-865739a3c2eb" TYPE="swap"    

 # 현재 swap 영역을 사용하고 있으면 해제할 수 없다.
 # swap 영역이 여러개일 때
[root@centos7:~]# swapoff  /dev/mapper/centos-swap

 # 현재 모든 swap을 해제 할 때
[root@centos7:~]# swapoff -a

# 해제 여부 확인.
 # swap 이 모두 0B인 것을 확인할 수 있다.
[root@centos7:~:]# free -h
              total        used        free      shared  buff/cache   available
Mem:            62G        7.7G         52G        161M        3.0G         54G
Swap:            0B          0B          0B
# swap 파티션 마운트 정보 변경
[root@centos7:~:]# vi /etc/fstab
/dev/mapper/centos-root /                       xfs     defaults        0 0
UUID=d675d2d3-80c0-1234-8j72-6b5323dd2c01 /boot                   xfs     defaults        0 0
# type이 swap 인 파티션에 대해 주석 처리 해 준다.
# 삭제 해도 된다.
#/dev/mapper/centos-swap swap                    swap    defaults        0 0
/dev/sdb1       /data  xfs     defaults        0       0