Typeorm query()문 치명적인 단점

InnomDB·2022년 8월 4일
0

typeorm

목록 보기
3/5


오랜만에 돌아왔습니다.
귀찮아서 오랜만에 돌아온것이 아니라 막상 글을 쓸 주제가 없었습니다...

하지만 드디어 글을 써야겠다라고 마음을 먹을 수 있게 된 주제가 바로 typeorm에서의 rawquery를 쓸 때 사용하는 query()문입니다!!

이전 포스팅에서 typeorm으로 union을 사용한적이 있습니다. 그 때 바로 query()문을 사용하였습니다.

그렇다면 대체 무엇이 치명적인 단점일까요?? 어그로?? 아닙니다!!!
제 기준에선 치명적인 단점이 맞습니다!! 그것에 대해 지금부터 알아보겠습니다!!

고고고!!! 후비고~ 렛츠고~

먼저 저의 상황을 설명드리면 DB(Mysql)를 쓸때 조회용 DB(Slave)와 삽입, 수정, 삭제 DB(Master) 2개로 나눠서 사용하고 있습니다.

나눠서 사용하는 이유는 뭐 별거 없습니다. DB에 부담을 덜 주기 위해서 입니다~
나는 뭐 1개로 충분해 하시는분은 뒤로가기를 눌러주시면 됩니다~ 그런분은 보실 필요 없습니다.

핵심은 바로 아래와 같습니다.

 All simple queries performed by find methods or select query builder are using a random instance

TypeORM Replication
찾기 메서드 또는 선택 쿼리 작성기에 의해 수행되는 모든 단순 쿼리는 임의 인스턴스를 사용합니다.
(파파고 만세!!)

임의 인스턴스를 사용한다고 합니다.. 랜덤 인스턴스 즉, 마스터를 사용할 수도 있다고 하는 것이죠
저는 왜 이걸 이제서야 알았을까요?? 이것도 사수가 알려줘서 알았습니다..

이 문제를 해결하는 방법은 간단합니다.

const slaveQueryRunner = dataSource.createQueryRunner("slave")
try {
    const userFromSlave = await slaveQueryRunner.query(
        "SELECT * FROM users WHERE id = $1",
        [userId],
        slaveQueryRunner,
    )
} finally {
    return slaveQueryRunner.release()
}

위와 같이 createRunner에 instance를 직접 지정하면 됩니다. 하지만 진짜 잘 동작 되는지 궁금하기 때문에 local에서 테스트 해보기로 결정했습니다.

로컬 테스트

로컬에서 테스트 하기 위해서는 우선 DB를 2개 사용해야 합니다. 그것을 저는 Docker로 구성했습니다.

// docker-compose.yml
// Mac m1용

version: '3'
services:
  coinness-local-db:
    platform: linux/x86_64    # 추가된 라인
    image: library/mysql:5.7
    container_name: mysql-test-container
    #restart: always
    ports:
      - 3306:3306
    environment:
      MYSQL_ROOT_PASSWORD: 본인 비밀번호
      TZ: Asia/Seoul
    volumes:
      - coinness-db-vol:/var/lib/mysql

  coinness-local-db_slave:
    platform: linux/x86_64    # 추가된 라인
    image: library/mysql:5.7
    container_name: mysql-test-container2
    #restart: always
    ports:
      - 43306:3306
    environment:
      MYSQL_ROOT_PASSWORD: 본인 비밀번호
      TZ: Asia/Seoul
    volumes:
      - coinness-db-vol2:/var/lib/mysql
    depends_on:
      - coinness-local-db

volumes:
    coinness-db-vol:
    coinness-db-vol2:

Compose up으로 구동시켜주시면 이제 Docker에 DB가 세팅되었습니다.

지금 부터 단계별로 세팅해보겠습니다.

1. 터미널에서 docker 확인

docker ps -a

위 사진을 보시면 mysql:5.7 두 개를 확인할 수 있습니다.
위의 명령어는 현재 실행중인 docker processor 전체를 확인하는 명령어 입니다.

2. master DB container 접속

저는 mysql-test-container를 master db로 정했기 때문에 여기로 먼저 접속해주겠습니다.

// 접속명령어
docker container exec -it 컨테이너ID bash

위와 같이 접속한 후 nano라는 에디터를 먼저 다운 받아주었습니다.(저는 개인적으로 나노를 좋아해서 나노를 받았습니다)

그리고 /etc/mysql/mysql.conf.d/mysql.conf (파일 경로)를 찾아 들어가

nano mysqld.conf

명령어를 입력하면 파일을 켜게되고 위의 사진 처럼 구성해주시면 됩니다!

server-id=1 서버를 식별하기 위해서 적는것으로 master DB가 1입니다.
log-bin=mysql-bin master DB에서 실행한 쿼리를 binary log로 남긴다는 의미 입니다.

나노 에디터에서 컨트롤 x 후 y (저장 후 종료)

이제 master 서버를 껏다가 다시 구동시켜주시고 컨테이너 접속 후

mysql -u root -p

mysql에 접속후 아래와 같이 명령어를 쳐주시면 됩니다.

본인의 상태를 어딘가에 잘 적어놓으시길 바랍니다.

Tip
혹시 모든 DB가 아니라 특정 DB만 복제하고 싶으시다면 아래의 세팅을 추가 해주시면 됩니다.

mysqld.conf

binlog_do_db = 내가 원하는 DB이름 

2. slave DB container 접속

master와 마찬가지로 진행하시면 됩니다.

slave의 mysqld.conf는 위와 같이 설정해주시면 됩니다!

slave도 부팅한번 해주세요~

3. DB dump

이제 이 글을 보시는 분들도 본인이 사용하는 DB가 있으실테니까 그걸 salve로 덤프 떠주시면 됩니다.
저도 master에 이미 사용하던 DB가 있어 slave로 옮겼습니다.

3 - 1. dump 파일 만들기 (master container에서 작업하시면 됩니다.)

3 - 2. dump file copy하기
dump파일은 현재 docker container안에 존재하는 것이기 때문에 실제 로컬로 copy하겠습니다.

3 - 3.dump file 가져오기(slave container에서 작업하시면 됩니다.)

slave container에 접속해 잘 가져와진것을 확인 할 수 있습니다.

3 - 4. dump file 적용하기

덤프 파일을 적용하기 전에 master DB의 데이터베이스(loacldb)와 동일한 이름의 db를 slave에도 미리 생성해주었습니다.

create database localdb;

!!!주의

dump 파일을 만들 때는 mysqldump고 파일을 붙여넣을 때는 mysql입니다. 이거 조심하셔야 됩니다.
저도 막 하다가 dump에 slave의 빈 db를 덮어씌기 해놓고 붙여넣는 명령어 겨우 찾아서 했는데 계속 빈 DB여서 빡쳤었습니다. 결국 빈 DB라는걸 깨닫고 처음부터 다시 해서 잘 적용했습니다 ㅎㅎ

Tip.
이제 DB까지 복사해놓고 나면 헷갈릴 때가 있습니다.. 뭐가 Master DB였지..?
그럴 땐 mysql에서 show master status 명령어를 입력하시면 오직 master DB에서만 정보가 나옵니다.

4 - 1. Master User 만들기

Master User이름만 들어도 master mysql에 접속합니다!!

use mysql
GRANT REPLICATION SLAVE ON *.* TO 'repluser'@'%' IDENTIFIED BY repluser;

아이디랑 비번은 원하시는걸로 만드셔도 상관없습니다~
이것을 만드는 이유는 slave가 접근할 마스터를 알아야하기 때문입니다.

4 - 2. Salve DB에 Master DB 정보 전달하기

CHANGE MASTER TO MASTER_HOST='본인 호스트 주소', MASTER_PORT=3306, MASTER_USER='repluser', MASTER_PASSWORD='repluser', MASTER_LOG_FILE='본인 마스터 로그 파일', MASTER_LOG_POS=본인 마스터 로그 포스;

호스트 주소를 대체 어떻게 파악하는거야?? 하시는분은 아래의 명령어로 확인해주세요!

docker inspect 컨테이너ID

컨테이너 바깥에서 명령어 치시면 됩니다.

그리고 상단의 CHANGE MASTER를 mysql에다가 냅다 때리세요!!(IPAddress라고 써져있는 주소입니다.)
그 다음 show slave status로 정보를 확인합니다!

4 - 3. Slave Start

start slave

이제 모든 구성이 끝났습니다!!
master db를 바꾸시면서 slave에 복제가 잘 되는지 확인해보시면 됩니다.

Error Tip

MySQL replication error: Slave failed to initialize relay log info structure from the repository

이 문제는 복제를 다시 시작하시면 됩니다.

Step1.

  • Slave mysql root 계정 접속

Step2.

show slave status\g;

결과에서 Master_Log_File 및 Read_Master_Log_Pos 값을 잘 확인하세요.

Step3.

CHANGE MASTER TO MASTER_HOST='host 주소', MASTER_USER='user', MASTER_PASSWORD='password', MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS= 154;

다시 세팅하기 전에 Master에서 바뀐건 없는지 master mysql로 들어가 show master status\g로 확인해봅시다! 저는 제가 위에서 다 적어준 정보를 가지고 적어놓았습니다. 이 편이 이해가 쉬울시거 같아서요 ㅎㅎ

주의
혹시라도 host 주소에 저처럼 0.0.0.0 쓰시면 큰일납니다..
저는 도커 구성할때 0.0.0.0:3306 으로 둘 다 구성했는데 0.0.0.0으로 설정해주니 server-id가 중복된다는 오류가 떴었습니다.
이걸로 시간 한참 버렸습니다!!
그니까 주의 주의!!

Step4.

start slave;

슬레이브를 재시작합니다!

여기서 또 에러가 뜰 수 있습니다. slave가 실행중입니다~ 뭐 이런 류의 에러인데 우선 아래의 명령어를 입력합시다.

stop slave

그래도 안된다?

stop slave IO_THREAD;

둘다 때리면 저의 경우는 무조건 멈췄습니다.

슬레이브 서버를 이처럼 멈추고 슬레이브를 재세팅해봅시다!!

참고1.
참고2.
겸손한 개발자의 기록
Docker를 사용한 MySQL 마스터-슬레이브 복제
MySQL에서 복제를 설정하는 방법
현재 상태 확인하는 명령어 (현재 connection개수 확인 등)

진짜 마지막으로 이제 제대로 slave로 connect가 되는지 확인하는법

show status like 'Threads_connected';

계속해서 추가하게 되네요.. 혹시라도 mysql-bin파일을 보고싶으시다면 /var/lib/mysql 경로 안에 있습니다! docker 컨테이너 접속 후 위의 경로로 찾아가서 살펴보시면 됩니다.!!

profile
이노오오옴

0개의 댓글