본문 바로가기

기타

MySQL AUTO_INCREMENT의 문제점

728x90

 

당연하게 AUTO_INCREMENT를 써왔는데, 이 전략이 안좋다는 이야기가 있어서 조사해봤다.

 

1.  AUTO_INCREMENT란?

 

MySQL에서 기본 키를 생성하는 전략이다. INSERT할떄마다 키를 1씩 증가시켜준다.

 

결과

2. AUTO_INCREMENT 의 문제점

 

1) 분산형 시스템에서 문제가 발생한다.

(실제 규모 있는 시스템은 아래 그림과 같이 여러개의 웹서버와 웹 어플리케이션 서버가 여러개의 데이터베이스로 구성된 분산형 시스템으로 구성되어진다.)

 

여러 데이터베이스가 있는 상황에서 insert를 한다고 생각하자. 별다른 동기화가 되어있지 않다면, 데이터베이스 A 가 insert를 받으면 1,2,3,4,5,6으로 키가 증가할거고, 데이터베이스 B 또한 insert 쿼리를 받으면 1,2,3,4,5,6으로 키가 증가할것이다. 즉 Duplicate Key가 발생하여 데이터 일관성에 문제가 생길 것이다.

 

2) 키를 예측하기 쉬워진다.

Auto_increment 전략은 키를 예측하기 쉬워진다.  만약에 AUTO_INCREMENT 정책을 사용한다면, 경쟁사 회사의 고객수를 알기 위해서 아이디를 만들고 url를 통해 primary 키를 알아내기만 하면 된다.  또한 키를 예측하기 쉽기 때문에 SQL Injection 공격에도 취약해진다.

 

3. UUID (Universally Unique ID)

UUID는 128비트 데이터로 100% unique하다고 보장받지는 못하지만 충돌할 가능성이 굉장히 낮은 키다.

(킹무위키에 따르면 약 10^-38 의 확률이라고 써있다. 1초에 UUID를 1000만개씩 만들어도 8925년동안 만들어야한다고 한다.)

en.wikipedia.org/wiki/Universally_unique_identifier#Collisions

 

Universally unique identifier - Wikipedia

From Wikipedia, the free encyclopedia Jump to navigation Jump to search 128-bit number used to identify information in computer systems A universally unique identifier (UUID) is a 128-bit number used to identify information in computer systems. The term gl

en.wikipedia.org

 

UUID 는 RFC 4122 에서 정의되어있으며 tools.ietf.org/html/rfc4122

 

간단히 요약하자면 UUID는 128비트 고유한 값으로 어떠한 시스템에도 의존하지 않고 uuid를 생성해준다.

ver1에서는 기기의 하드웨어 주소값인 MAC 주소와 타임스탬프를 이용해서 만들며

mysql에서는 내부적으로 ver1 방식을 사용하고 있다.

 

위는 같은 PC의 MySql (Select UUID())를 이용하여 UUID를 여러번 생성한 결과다.

첫 3번째 숫자그룹은 타임스탬프고 뒤에가 MAC 주소라고 한다.

 

반면  자바에서는 내부적으로 완전 랜덤한 데이터를 생성하는 ver4 방식을 사용하고 있다고 한다.

 

 

RFC 4122 - A Universally Unique IDentifier (UUID) URN Namespace

[Docs] [txt|pdf] [draft-mealling-...] [Tracker] [Diff1] [Diff2] [Errata] PROPOSED STANDARD Errata Exist Network Working Group P. Leach Request for Comments: 4122 Microsoft Category: Standards Track M. Mealling Refactored Networks, LLC R. Salz DataPower Tec

tools.ietf.org

 

UUID 는 자바 5 에서부터 지원하고 java.utill.UUID 패키지에서 제공하며 다음과 같이 생성할수 있다.

UUID.randomUUID()

또는, @GenericGenerator 어노테이션을 이용해서 다음과 같이 생성자를 등록할 수도 있다.

 

그 결과 다음과 같이 쿼리가 생기는 걸 볼 수 있다.(이 결과는 ver4 방식이므로 매번 완전 랜덤한 결과값을 생성한다)

 

하지만, UUID를 쓸경우 BINARY(16)이나, VARCHAR를 써야한다. 기존의 INT 타입을 쓰는 AUTO_INCREMENT방법보다 메모리를 더 많이 차지하게 되고,  서버에서 uuid를 생성해야하므로 insert할때 시간이 더 걸린다는 단점을 가지고 있다.

4. 결론

단일 DB를 쓰면 AUTO_INCREMENT를 키로 쓰자. (성능, 메모리 측면에서 더 낫다.)

다중 DB를 사용하는 분산형 환경이면 데이터 일관성을 위해 UUID를 키로 쓰는 걸 고려해보자

 

'기타' 카테고리의 다른 글

MSA 하는데까지 만들어보기 - (1)  (0) 2020.09.23
JUnit - 1  (0) 2020.08.17