2022. 2. 8. 16:37ㆍ기타
코드스쿼드 9번째 CS 미션을 진행했다.
docker 컨테이너로 MYSQL 5.7 버전을 설치 후 이것저것 만져보는 것이 미션의 핵심이다.
개인적으로 docker는 이름만 들어보고 사용하는 것은 이번이 처음인데, 명령어 한줄로 환경이 세팅된다는게 너무 간편했다.
docker run --name mysql-container -e MYSQL_ROOT_PASSWORD=password-d -p 3306:3306 mysql:5.7
docker run 명령어로 이미지를 불러와서 컨테이너를 생성했다.
docker exec -it mysql-container bash
bash 환경에서 작업하기 위한 커맨드.
mysql5.7 컨테이너 이므로 mysql에 접근해 작업을 진행한다.
mysql -u root -p
mysql에서는 기본 언어 인코딩 설정이 latin1으로 되어있다.
미션을 진행하면서 생각난 일인데, 작년에 AWS RDS에 mysql을 세팅하면서, 당연히 UTF-8이 default 설정이라고 생각하고 여러가지 작업을 한 후 기본적인 한글 데이터 읽기 쓰기를 진행하니 글자가 모두 깨져있었다. 설정과 테이블 생성, 유저 권한 등의 작업을 오랜기간동안 끝마치고 난 뒤라 latin1에서 UTF-8로 설정을 바꾸는 것이 참 힘들었다. 처음부터 다시 설정을 잡기는 막막해서 어쩔 수 없이 mysql workbench에서 gui로 하나하나 다 인코딩 설정을 바꾸었던 기억이 있다...
어쨌든 ! latin1을 utf8로 변경하기 위해, mysql config을 수정해야한다. 그런데, 경량화된 컨테이너라서 심지어 에디터도 깔려있지 않다.
apt-get install apt
apt update
apt install nano
나노 에디터를 깔아줬다. 그 후, /etc/mysql/mysql.conf.d/mysqld.cnf 파일을 열어서 수정한다.
nano /etc/mysql/mysql.conf.d/mysqld.cnf
------------------------------------ 아래내용으로 수정
[client]
default-character-set = utf8mb4
[mysqld]
init-connect = 'SET collation_connection = utf8mb4_unicode_ci'
init-connect = 'SET NAMES utf8mb4'
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
default_time_zone='+09:00'
[mysql]
default-character-set = utf8mb4
[mysqldump]
default-character-set = utf8mb4
적용 후,
service mysql restart
명령으로 설정을 적용한다.
이후 사용은 mysql을 일반 cli환경에서 사용하는것과 같다.
JDBC로 docker mysql에 접속해보았다.
JDBC 설정은 '데이터베이스 개론과 실습' 책과 https://mozi.tistory.com/137 글을 참고했다.
public static void main(String[] args){
String Driver="";
String userid="root";
String userpw = "password";
Connection conn = null;
String url="jdbc:mysql://127.0.0.1:3306/mission2";
try{
Class.forName("com.mysql.cj.jdbc.Driver");
System.out.println("로드 성공");
}catch(ClassNotFoundException e){
e.printStackTrace();
}
try{
conn=DriverManager.getConnection(url,userid,userpw);
System.out.println("연결성공");
}catch(Exception e){
e.printStackTrace();
}
}
해당 코드로 드라이버를 로드하고, mysql에 접근했다.
의문인 것은, 컨테이너의 ip주소가 172.17.0.3 으로 설정되어있는데 이곳에 직접 접근하려고 하면 접근이 불가능하다.
String url="jdbc:mysql://localhost:3306/mission2";
같은 방식으로 localhost를 넣고 접근해야 정상적으로 접근이 가능했다.
개인적으로 예상되는 점은, docker에서 포트포워딩으로 ip가 열려있어서 3306 포트만으로 접근을 구분하고 localhost에서 자동으로 172.17.0.3으로 길을 터준다(?)는 가설을 생각해봤는데 아직은 잘 모르겠다.
mysql에 더미 데이터를 100만건 넣는 미션을 진행했다.
user_log 라는 테이블에 insert문으로 데이터를 넣어야한다.
nickname varchar(64),
money dec(10, 2),
last_visit datetime
데이터 생성 규칙
- 사용자 nickname 은 영어 단어 100개 + 랜덤 문자열 3자리 + 랜덤 숫자 4자리로 생성한다.
- money 는 1부터 100,000 사이 값을 적당하게 분포하게 만든다.
- last_visit 은 최근 한 달 사이로 랜덤 시각으로 생성한다.
처음에는 jdbc로 java의 기능을 이용해서 데이터를 생성해서 insert문에 string만 넣어주는 방식으로 하려고 했는데, 조금 돌아가기로 했다.
mysql의 프로시져를 활용하는 방법!
DELIMITER $$
CREATE PROCEDURE insertDATA()
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE A VARCHAR(64) DEFAULT 'zzang';
WHILE (i <= 1000000) DO
SET A = concat("zzang_",LEFT(UUID(), 7));
INSERT INTO user_log VALUES ( A, FLOOR(1 + rand() * 100000 ), FROM_UNIXTIME(FLOOR(unix_timestamp('2022-01-07 00:00:00')+(RAND()*(unix_timestamp('2022-02-07 00:00:00')-unix_timestamp('2010-01-01 00:00:00'))))) ); -- ⓓ 테이블에 i값 넣어주기
SET i = i + 1; -
SET A = 'zzang';
END WHILE;
END$$
DELIMITER ;
문법은 조금 생소하지만 읽는데 부담은 없다. concat을 통해 문자열을 합치고, rand로 난수를 생성해서 때려박았다.
그런데, 이렇게 백만번의 루프를 돌며 insert를 수행하니 모두 수행하기까지 10분이 넘게 걸렸다.
성능향상을 위해 AUTOCOMMIT 설정을 바꿨다.
default 값은 TRUE인데, 데이터의 update가 일어날 때 마다 commit을 진행하게 돼서 반복적인 update를 진행할 때는 오버헤드가 너무 커지게 된다.
따라서
SET AUTOCOMMIT = FALSE;
를 설정해서 데이터의 변경이 한꺼번에 이루어지도록 조정했다.
물론 모든 작업이 끝난 후에는
SET AUTOCOMMIT = TRUE;
로 변경해야 데이터가 삽입된다.
'기타' 카테고리의 다른 글
nGrinder + Springboot 부하 테스트 튜토리얼 (8) | 2022.08.27 |
---|---|
MySQL + docker + python 더미데이터 십만개 넣기! (0) | 2022.07.01 |
[CI/CD] github action 맛보기 기록 (1) | 2022.06.28 |
[대규모 시스템] 대용량 데이터 처리의 어려움 (2) | 2022.06.21 |
인프런 HTTP 강의 공부기록 (0) | 2022.03.01 |