[DB] 기초부터다시, ACID, CAP

DB|2020. 9. 14. 15:53

ACID

트랜잭션은 이러한 성질을 만족해야 안전하게 수행됬다고 볼수 있다는 특징들의 약자

 

A : Atomicity, 원자성, 트랜잭션 내에 작업은 모든 상태가 반영되거나, 모든 상태가 되지 않아야 한다.

C : Consistency, 일관성, PK 규정이라거나, 타입 상태의 규정, 및 규정들은 언제나 일관성있도록 깨지지 않아야한다.

I : Isolation, 독립성, 트랜잭션 수행내용은 다른 트랜잭션이 끼어들지 못하도록 해야한다

               (성능상에 이유로 유연성 있는 제약조건이라고 함, 커밋되지 않은 항목에 대한 읽기 라거나 여러 조건들이..)

               (DB는 보통 낙관적으로 커밋될것이라 처리하기 때문에 일단 반영하고 트랜잭션 밖에서 select 요청이 들어오면 redo로그..? 를 통해 해당 트랜잭션 버전에 맞게 변경 후 보여준다고 한것 같은데.. 이러한 성능 저하를 겪지 않으려는 목적인듯함.. 내용이 틀리다면 피드백 부탁드립니다.)

D : Durability, 지속성, 트랜잭션이 성공하면 해당 내용은 언제나 반영되어있어야 한다, 커밋 후 장애가 발생하더라도 로그를 통해서라도 복구가 가능해야 한다.

 

CAP

어떤한 분산 시스템도 CAP(Consistency, Availability, Partition tolerrance) 3가지를 동시에 만족시킬수 없다는 이론

 

C(Consistency, 일관성) : 모든 서버들은 같은 시간에 같은 내용의 데이터를 보여주는것을 보장해야 한다.

A(Availability, 가용성) : 언제나 모든 사용자들이 읽기 및 쓰기가 가능해야 하며, 다른 서버의 장애시에 영향을 받아서는 안된다.

P(Partition tolerrance, 분할내성) : 시스템 일부가 장애에 빠져도 시스템을 서비스 할 수 있어야 한다.

 

출처 :  rndblog.github.io/nosql/architecture/2015/09/13/notes-on-nosql-basics.html

전통적인 RDB는 C와 A를 만족하여 트랜잭션을 통해 데이터 일관성과 단일 서버를 통한 가용성을 제공하낟.

 

또한 NoSQL의 경우 C와 P를 만족하기 위하여, 분산 환경을 제공하고, 분산환경에서 일관성을 제공하기 위해 분산 서버간의 sync 작업이 진행되며, 일관성을 맞추는 sync작업이 진행되는동안 클라이언트가 read/write가 불가능 할수 있기 때문에 A가 포기된다..

 

AP를 선택한 CouchDB, Cassandra의 경우 C를 만족하지 않기 때문에 여러 클라이언트가 일관성 없는 데이터를 바라볼수 있지만, 언제나 읽고 쓸수 있도록 A 를 제공하고 분산 환경인 P를 제공하기 때문에

데이터 일관성이 꼭 중요하지 않는 경우에 선택된다. 

 

 

'DB' 카테고리의 다른 글

GraphQL 끄적끄적  (0) 2020.08.20
기초부터다시, 조인  (0) 2020.08.18
[MongoDB] 해킹된 후 보안 설정 관련  (0) 2019.12.23
[MyBatis] MyBatis 문법 파서  (0) 2019.05.29
DB 스키마를 관리하자  (0) 2018.12.20

댓글()

GraphQL 끄적끄적

DB|2020. 8. 20. 20:17

GraphQL을 들어본것은 오래됬지만, 클라이언트 단에서 질의를 날린다는게 위험할것 같기도 하고

굳이 불필요 할 것 같아 어떻게 사용하고 동작하는지 파악하지 않았었습니다.

 

하지만, 요즘 많은곳에서 사용되는것들을 보며 대략적으로 어떻게 사용하며

어떻게 동작하는지 살펴보려고 합니다.

 

살펴보기 이전에 GraphQL을 사용하는 이유, GraphQL의 강점을 살펴보자면

기존 많이 사용하는 REST API의 경우 각 쿼리에 대해서 url을 설계하고

해당 url으로 주는 값은 언제나 형태가 고정적이였습니다.

하지만, 업무에 따라 필요한 필드가 다름에도, 공개되어있는 API의 응답의 형태는 동일할 것이기 때문에

클라이언트에서 필요없는 데이터 및 필드들은 알아서 필터링해서 사용해야 했습니다.

 

그리고 매번 새로운 형태의 API가 필요하다면 url을 계속해서 추가해야 합니다.

두개의 리소스를 얻기위해서는 두번의 URL 요청을 해야 합니다.

 

하지만, GraphQL을 사용하게 되면, 필요한 필드만을 응답으로 받을수 있고

여러 리소스들을 한번의 요청으로 받아올 수 있습니다.

 

간단하게는, 클라이언트단에서 여러 요청 및 응답을 유연하게 처리할 수 있게 됩니다.

 

일반적으로, GraphQL은 여러 URL이 아닌 하나의 URL을 통해 처리합니다.

(보통 설정으로 path는 수정할 수 있겠지만, 기본값은 /graphql 을 사용합니다.)

 

그리고 모든 리소스, 그리고 모든 필드를 클라이언트가 조회할 수 있게 된다면

보안상 문제가 될수 있기 때문에

graphqls를 확장자의 파일에 정의된 것만 질의 할 수 있게 되어있습니다.

 

제가 작성한 item.graphqls은

schema{
    query: Query
}

type Query{
    allItems: [Item]
    item(id: Float): Item
}

type Item{
    id: Float
    name: String
}

실제로 Item에는 price와 같은 필드들이 존재하지만 graphqls에 Item에는 존재하지 않기 때문에

질의로 얻을 수 없습니다.

 

이에 대응하는 서버 로직을 작성하는 방법은 여러가지가 있겠지만

제가 작성한 방법은 SpringBoot에서 GraphQLQueryResolver를 사용하여 테스트를 진행해 보았습니다.

 

/graphql 로 요청을 보낼때는 GET, POST 모두 지원하지만 요청 방식이 조금씩 다릅니다.

해당 내용은 https://graphql-kr.github.io/learn/serving-over-http/ 을 참고하시면 될것 같으며

 

POST에 대략적인 사용방법은 request content-type은 application/json으로 하고

아래 처럼 바디에 json 형태로 질의를 요청합니다.

{
	"query" : "{result : allItems{id name}}"	
}

위 쿼리는 "allItems를 응답으로 받을껀데, id, name필드를 받을꺼고 result라는 필드에 데이터를 담아서 받고 싶다"가 됩니다.

물론 이것은 테스트로 작성했기에 파라미터 없이 모든 데이터를 받게 했지만

이런 쿼리를 노출한다면, 부하로 인해 문제가 생길수 있겠습니다.

 

이에 응답은 아래와 같은 형태가 됩니다.

{"data":{"result":[{"id":1.0,"name":null},{"id":2.0,"name":null}]}}

 

하나 더 살펴본다면, 아까 언급한것 처럼 기존에는 두번의 요청을 보내야 하는경우를 graphQL은 한번의 요청으로 처리 할 수 있습니다.

{
	"query" : "{result : allItems{id name},result2 : item(id: 1){name}}"
	
}

방금 요청한 모든 Item을 가져오는 결과를 'result'필드로 응답 받고, id 1번에 대한것은 'result2'로 응답을 달라는 질의 입니다(여기서는 같은 item이지만 일반적으로는 같은 리소스가 아니겠지요)

 

 

이에 응답은 아래와 같은 형태가 됩니다.

{"data":{"result":[{"id":1.0,"name":null},{"id":2.0,"name":null}],"result2":{"name":null}}}

 

바로 적용하지는 않을 예정이기 때문에 간단한 사용방법과 사용 까닭 정도 파악을 위해 테스트 해보았고

끄적끄적 정리해보았습니다.

 

추후 더 파악되는 내용 및 기억하기 위해 기록으로 남겨놓을 내용들이 있다면 기록할 예정입니다

감사합니다.

'DB' 카테고리의 다른 글

[DB] 기초부터다시, ACID, CAP  (0) 2020.09.14
기초부터다시, 조인  (0) 2020.08.18
[MongoDB] 해킹된 후 보안 설정 관련  (0) 2019.12.23
[MyBatis] MyBatis 문법 파서  (0) 2019.05.29
DB 스키마를 관리하자  (0) 2018.12.20

댓글()

기초부터다시, 조인

DB|2020. 8. 18. 19:55

Inner Join

'A' INNER JOIN 'B': A,B 교집합

 

Outer Join

'A' LEFT OUTER JOIN 'B' = A

'B' LEFT OUTER JOIN 'A' = B

'A' FULL OUTER JOIN 'B' = A, B 합집합(즉 순서 상관없음)

 

cross join

모든 경우의 수

ON절이 없음

A CROSS JOIN B

SELECT A.field, B.field FROM A, B

 

equal join

동일 값을 중심으로 조인

SELECT A.field, B.field FROM A,B WHERE A.field=B.field

 

Natural join

동일 컬럼을 내부적으로 모두 조인하여 ON 절 생략 가능

SELECT A.field FROM A NATURAL JOIN B

 

조인 연산중 Plan에서 만날수 있는 내부 동작 조인

 

Nested Loop Join

(어딘가에서는 NL Join이라고 불리기도..)

for내에 for 동작과 같음

for(A a : Atable){

  for(B b : Btable){

  }

}

결국 A데이터와 B 데이터가 많을수록 오래걸리는것은 당연하고

A의 값에서 B 값을 찾는데 인덱스가 없으면 코스트(cpu)가 급격히 올라가게 된다

 

 

Sort Merge Join

정렬후 찾는 방식, 연산이 =가 아닌경우 유리한 방식

두 테이블의 크기가 차이가 많이 나면, 소팅하느라 오래 걸리기 때문에 비효율적임

(select에 컬럼 내용 모두 소팅에 포함되어, select 컬럼을 줄이면 도움이 됨)

 

 

Hash Join

해싱 함수를 이용하여 조인 대상을 특정 지역에(partition)에 모아두어 해시값으로 테이블에 조인하는 방식

대용량 처리에 유리

 

 

이미지 출처 : http://wiki.gurubee.net/pages/viewpage.action?pageId=26744589

'DB' 카테고리의 다른 글

[DB] 기초부터다시, ACID, CAP  (0) 2020.09.14
GraphQL 끄적끄적  (0) 2020.08.20
[MongoDB] 해킹된 후 보안 설정 관련  (0) 2019.12.23
[MyBatis] MyBatis 문법 파서  (0) 2019.05.29
DB 스키마를 관리하자  (0) 2018.12.20

댓글()

[MongoDB] 해킹된 후 보안 설정 관련

DB|2019. 12. 23. 19:57

라즈베리파이에 토이프로젝트로 끄적끄적 돌리고 있는 서비스들이 있습니다.

아직 외부에는 거의 오픈하지 않아(하나는 카카오 채널을 통해 접속 가능하도록..^^;;)

개인적으로 저만 사용하고 있었죠

(디비는 MongoDB를 사용중이였습니다.)

 

그런데 주말에 접속해보니 서비스중 하나의 페이지가 정상적으로 나오지 않았습니다.

 

"응..? 매일마다 정해져있는 정보를 보여주는 간단한 서비스라 딱히 장애날부분이 없을텐데.. 뭐지? 버근가..?" 라는 생각을 하며 월요일 확인해보니 

있어야할 디비 데이터가 없습니다..

(물론 백업이 있기에 간단히 복구 할수 있지만..)

 

"응? 왜 갑작이 데이터가 날아갔지?" 라는 생각을 하며 db 접속해보니 이상한 db가 하나 추가 된것을 확인했습니다.

허허허..털렸네요...

(물론 서비스중이 아니기에 비트코인을 보내고 복구할필요도 없지만 말입니다.. ㅎㅎ)

 

사실 제 시스템은 털기 아주 간단하긴 했습니다..

개인적으로 테스트로만 사용중이기 때문에 아주아주 취약한걸 알고도 보안을 전혀 신경쓰지 않았습니다.

(당연히 해야되는거지만.. 테스트용으로 구성한거라..^^;;;)

 

그래도 이렇게 들어와서 데이터를 날린다면 귀찮으니 조금의 보안을 위해 조치를 해보며

글을 남깁니다.

 

 

1. 먼저, 현재 라즈베리파이는, 공유기의 포트포워딩을 통해 접근할 수 있도록 열어 놓았고, 마찬가지로 DB 포트도 열려있습니다, IP 제한도 없고, 포트도 27017로 동일하게 열어 놓았었습니다.

-> DB 접근은 어플리케이션 IP만 및 제 개발 PC 만 열어놓아야 하는것이 맞겠지만, 이 부분은 여전히 편의성을 위해 설정하지 않을 예정입니다.

-> 포트를 27017을 그대로 사용하지 않고 임의의 포트로 수정하였습니다(무작위 아이피로 몽고 공식 포트로 찔려보는것이였을 꺼라 생각합니다.)

 

2. 계정은 생성해뒀지만, 최근 테스트를 위해 "authorization: disabled" 상태로 두었었습니다. 이러니 간단히 털수 있었겠죠

-> authorization: enabled 로 변경 하였습니다. 그리고 기존 계정은 삭제하고 새로 생성했습니다.

 

더더욱 많은 보안들을 적용할 수 있겠지만 아주 간단한 조치만으로도

왠만한 해킹들에 대해서는 막힐것이라 기대합니다

(또 털리면 다시 글을 남기게 되겠지요)

 

3. 서비스중 하나는 동적으로 데이터가 쌓이지 않아 백업이 다 되어 있지만, 하나의 서비스는 계속해서 크롤링하여 데이터를 쌓는데 백업이 되어있지 않았습니다.

(물론 실서비스가 아니기에 신경을 쓰지 않았지만요...)

-> 추후 데이터 백업 관련하여 적용해야겠습니다.

 

4. 이제 변경된 계정 정보 및 포트들을 적용해야하는데, spring config server를 사용하고 있기 때문에 간단히 git repo의 설정 정보를 변경하는것으로 간단히 적용되었습니다.

 

 

요약

1. 공식 포트를 그대로 사용하지 말자!(SSH 포트인 22라던지.. 디비포트 1521이나 27017이라던지)

2. 계정 보안을 켜두고 쓰자

3. 데이터는 늘 백업하자

 

 

'DB' 카테고리의 다른 글

[DB] 기초부터다시, ACID, CAP  (0) 2020.09.14
GraphQL 끄적끄적  (0) 2020.08.20
기초부터다시, 조인  (0) 2020.08.18
[MyBatis] MyBatis 문법 파서  (0) 2019.05.29
DB 스키마를 관리하자  (0) 2018.12.20

댓글()

[MyBatis] MyBatis 문법 파서

DB|2019. 5. 29. 19:13

업무상 MyBatis를 그대로 활용하기보다 해당 기능을 녹이고

MyBatis 문법을 가능한 그대로 입력 받기 위해, 그리고 파싱하기위해 

MyBatis 문법을 파악하고 녹일 필요가 있었다.

 

MyBatis은 보통 XML 파일에 작성이 되며 내부 문법도 XML 문서내에 xml 형식으로 입력된다.

 

대략 작성해보면...(parameter랑 다 생략)

ex)

<select id="aaa">

  SELECT ename, empno, dept FROM EMP

  <where>

  <if test="ename !=null">

      ename=#{ename}

  </if>

  </where>

</select>

 

지금 예로는 if element 안에 test라는 attribute가 나온다는걸 알수 있는데

메뉴얼만 보기에는 모든 attribute나 element가 어떤것들이 더 사용되는지

element간에 관계가 어떻게 되는지 파악하기 어렵다

(예를 들어 <select>안에 <where> 가 들어갈수 있는데 <if>안에는 어떤 element가 들어갈 수 있는지)

 

그래서 혹시 xsd(XML Schema Definition, 말그대로 XML의 정의서)이 없을까?

해서 소스를 열어보니 마침 xsd 파일이 존재 했다

 

mybatis/org.apache.ibatis.builder.xml/mybatis-mapper.xsd

 

업무상 문법을 확장할 필요도 있기 때문에 그대로 가져다 사용하진 않았지만

xsd 파일을 통해 element관계가 엮이고 엮여있는것을 확인했고

덕분에 문법(입력할 element) 들을 빠르게 파악할수 있어

mybatis에 대한 파서를 커스텀 하여 만들수 있었다.

 

 

 

 

 

'DB' 카테고리의 다른 글

[DB] 기초부터다시, ACID, CAP  (0) 2020.09.14
GraphQL 끄적끄적  (0) 2020.08.20
기초부터다시, 조인  (0) 2020.08.18
[MongoDB] 해킹된 후 보안 설정 관련  (0) 2019.12.23
DB 스키마를 관리하자  (0) 2018.12.20

댓글()

DB 스키마를 관리하자

DB|2018. 12. 20. 14:12

제품 혹은 프로젝트를 진행할때 계속 테이블 스키마가 변경되거나

샘플 데이터가 변경되는 경우들이 있다.


보통 SQL 파일을 소스들과 함께 git에 버전 관리를 하고 있는데


실제 적용된 제품 버전이야 Version.class 라거나 커맨드를 통해 버전을 확인하면 되지만

DB에 어떤 버전까지 적용되어 있는지는 파악하기 어려울때가 있다.


그리고 git에는 최신 sql만을 관리해왔기 때문에 각 버전마다 어떤 스키마들이 변경되었는지

현재 버전에서 최신자로 적용시 어떤 어떤 컬럼들이 변경되었는지는


git 히스토리들을 하나 하나 파악해야하는 귀찮음이 존재했다

(서버가 여러개면 덤으로.. 버전마다 alter문을 만들어야하는....)


그래서 스키마를 관리해주는 툴이 없을까 싶어 살펴보니

데이터베이스 형상관리 툴이라는 이름의 두가지가 spring boot starter에 포함 되어있었다

(spring boot와 연동하여도 사용하고 cmd로 직접도 사용할 예정..)


flyway(https://flywaydb.org/)

liquibase(https://www.liquibase.org)


다음 글에서는 flyway


그리고 그 다음에는 liquibase


마지막으로는 각각 비교를 해볼까 한다.

(잠깐 사용해봤을때는 liquibase 가 더 좋아보인다..)

'DB' 카테고리의 다른 글

[DB] 기초부터다시, ACID, CAP  (0) 2020.09.14
GraphQL 끄적끄적  (0) 2020.08.20
기초부터다시, 조인  (0) 2020.08.18
[MongoDB] 해킹된 후 보안 설정 관련  (0) 2019.12.23
[MyBatis] MyBatis 문법 파서  (0) 2019.05.29

댓글()