mysql 간의 데이터 전송에 Embulk를 사용해 보았습니다.

17394 단어 MySQLEmbulk
이 기사는 MicroAd Advent Calendar 2020의 19 일째 기사입니다.

Embulk을 처음 사용하는 사람들이 시도에 사용한 기사입니다.

소개



MySQL에서 BigQuery로 데이터를 전송할 수있는 기회가 있었고 좋은 방법이 없다고 생각하면 Embulk를 만났습니다.
동작 확인을 위해 docker-compose에서 MySQL 컨테이너를 세워서 MySQL 간의 데이터 전송을 수행했기 때문에 요약합니다.

매우 편리했습니다.

Embulk이란?



공식 페이지( htps //w w. 에 m부 lk. rg/ )에서 인용

Embulk is a bulk data loader. It helps data transfer between types of databases, storages, file formats, cloud services, and else.



Embulk는 데이터베이스, 스토리지, 파일 형식 및 클라우드 서비스와 같은 유형 간의 데이터 전송을 지원하는 대량 데이터 로더로 MySQL뿐만 아니라 BigQuery 등으로 데이터를 전송할 수 있습니다.

사용해보기



이번에는 docker-compose에서 Embulk를 실행하는 컨테이너와 MySQL의 컨테이너를 연결하여 움직였습니다.
디렉토리 구조는 다음과 같습니다.

.
├── db1/
│      ├── Dockerfile
│      └── initdb.d/
│                  ├── schema.sql
│                  └── testdata.sql
├── db2/
│      ├── Dockerfile
│      └── initdb.d/
│                  ├── schema.sql
│                  └── testdata.sql
├── docker-compose.yml
└── embulk/
         ├── Dockerfile
         ├── config.yml
         └── seed.yml

MySQL의 Dockerfile은 이하 (db2/Dockerfile도 마찬가지)

db1/Dockerfile
FROM mysql:5.7
RUN touch /var/log/mysql/mysqld.log # 指定の場所にログを記録するファイルを作る

Embulk는 java8이 필요하기 때문에 java : 8 이미지를 기반으로 Embulk를 설치합니다.

embulk/Dockerfile
FROM java:8

# embulkインストール
RUN curl --create-dirs -o /usr/local/bin/embulk -L "https://dl.embulk.org/embulk-latest.jar" &&\
    chmod +x /usr/local/bin/embulk
# 各種プラグインインストール
RUN embulk gem install embulk-input-mysql
RUN embulk gem install embulk-output-mysql
RUN embulk gem install embulk-filter-concat
RUN embulk gem install embulk-filter-column
# RUN embulk gem install embulk-output-bigquery (BigQueyに転送する場合はこちらのプラグインが必要)

docker-compose.yml
version: '3.3' # docker-composeのversionを指定
services:
  db1:
    build: ./db1       
    restart: always
    environment:
      MYSQL_DATABASE: sample_db
      MYSQL_USER: user
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: rootpassword
    ports:
      - "3306:3306"
    volumes:
      - ./db1/initdb.d:/docker-entrypoint-initdb.d
  db2:
    build: ./db2      
    restart: always
    environment:
      MYSQL_DATABASE: sample_db
      MYSQL_USER: user
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: rootpassword
    ports:
      - "3307:3307"
    volumes:
      - ./db2/initdb.d:/docker-entrypoint-initdb.d
  embulk:
    build: ./embulk
    volumes:
      - .:/workspace
    stdin_open: true
    tty: true
    working_dir: /workspace

테이블은 적당히 초기치 넣어 둔다

db1/init.db.d/schema.sql
CREATE TABLE test (
    id INT NOT NULL AUTO_INCREMENT,
    name VARCHAR(32) NOT NULL,
    email VARCHAR(32) NOT NULL,
    PRIMARY KEY (id)
);

db1/init.db.d/schema.sql
INSERT INTO test (id,name,email) 
VALUES (1, 'aaa','[email protected]'), (2, 'bbb','[email protected]'), (3, 'ccc','[email protected]');

우선 컨테이너 시작
$ docker-compose up -d --build

확인
$ docker-compose ps

        Name                     Command             State                      Ports                   
--------------------------------------------------------------------------------------------------------
embulk-test_db1_1      docker-entrypoint.sh mysqld   Up      0.0.0.0:3306->3306/tcp, 33060/tcp          
embulk-test_db2_1      docker-entrypoint.sh mysqld   Up      3306/tcp, 33060/tcp, 0.0.0.0:3307->3307/tcp
embulk-test_embulk_1   /bin/bash                     Up  

embulk-test_db1_1의 MySQL에 레코드가 있는지 확인
$ docker exec -it embulk-test_db1_1 /bin/bash
$ mysql -u user -p
mysql> select * from test;

+----+------+----------------+
| id | name | email          |
+----+------+----------------+
|  1 | aaa  | [email protected] |
|  2 | bbb  | [email protected] |
|  3 | ccc  | [email protected] |
+----+------+----------------+
3 rows in set (0.00 sec)

이 테이블을 embulk-test_db2_1의 컨테이너에서 움직이는 MySQL로 전송하고 싶습니다.

Embulk로 전송



embulk 구성 파일 설명. yml로 작성.
MySQL의 경우 다음과 같은 느낌.
이번에는 입력과 출력이 모두 MySQL이기 때문에 각각 필요한 플러그인은embulk-input-mysqlembulk-output-mysql (사전 설치됨)

embulk/config.yml
in:
  type: mysql
  host: embulk-test_db1_1
  user: user
  password: password
  database: sample_db
  table: test
  select: id, name, email

out:
  type: mysql
  host: embulk-test_db2_1
  user: user
  password: password
  database: sample_db
  table: test
  mode: replace

(table과 select를 지정하고 있지만 직접 쿼리를 작성하는 방법도있다)

Embulk를 실행하기 전에 전송되는 내용을 미리 볼 수 있습니다.
$ embulk preview config.yml 

2020-12-13 07:53:45.496 +0000: Embulk v0.9.23
2020-12-13 07:53:46.237 +0000 [WARN] (main): DEPRECATION: JRuby org.jruby.embed.ScriptingContainer is directly injected.
2020-12-13 07:53:47.793 +0000 [INFO] (main): Gem's home and path are set by default: "/root/.embulk/lib/gems"
2020-12-13 07:53:48.353 +0000 [INFO] (main): Started Embulk v0.9.23
2020-12-13 07:53:48.453 +0000 [INFO] (0001:preview): Loaded plugin embulk-input-mysql (0.11.1)
2020-12-13 07:53:48.476 +0000 [INFO] (0001:preview): Loaded plugin embulk-filter-concat (0.1.0)
2020-12-13 07:53:48.516 +0000 [INFO] (0001:preview): Loaded plugin embulk-filter-column (0.7.1)
2020-12-13 07:53:48.538 +0000 [INFO] (0001:preview): JDBC Driver = /root/.embulk/lib/gems/gems/embulk-input-mysql-0.11.1-java/default_jdbc_driver/mysql-connector-java-5.1.44.jar
2020-12-13 07:53:48.546 +0000 [INFO] (0001:preview): Fetch size is 10000. Using server-side prepared statement.
2020-12-13 07:53:48.548 +0000 [INFO] (0001:preview): Connecting to jdbc:mysql://embulk-test_db1_1:3306/sample_db options {useCompression=true, socketTimeout=1800000, useSSL=false, user=user, useLegacyDatetimeCode=false, tcpKeepAlive=true, useCursorFetch=true, connectTimeout=300000, password=***, zeroDateTimeBehavior=convertToNull}
2020-12-13 07:53:48.727 +0000 [INFO] (0001:preview): Using JDBC Driver mysql-connector-java-5.1.44 ( Revision: b3cda4f864902ffdde495b9df93937c3e20009be )
2020-12-13 07:53:48.727 +0000 [WARN] (0001:preview): embulk-input-mysql 0.9.0 upgraded the bundled MySQL Connector/J version from 5.1.34 to 5.1.44 .
2020-12-13 07:53:48.728 +0000 [WARN] (0001:preview): And set useLegacyDatetimeCode=false by default in order to get correct datetime value when the server timezone and the client timezone are different.
2020-12-13 07:53:48.728 +0000 [WARN] (0001:preview): Set useLegacyDatetimeCode=true if you need to get datetime value same as older embulk-input-mysql.
2020-12-13 07:53:48.833 +0000 [INFO] (0001:preview): Fetch size is 10000. Using server-side prepared statement.
2020-12-13 07:53:48.833 +0000 [INFO] (0001:preview): Connecting to jdbc:mysql://embulk-test_db1_1:3306/sample_db options {useCompression=true, socketTimeout=1800000, useSSL=false, user=user, useLegacyDatetimeCode=false, tcpKeepAlive=true, useCursorFetch=true, connectTimeout=300000, password=***, zeroDateTimeBehavior=convertToNull}
2020-12-13 07:53:48.841 +0000 [INFO] (0001:preview): SQL: SELECT id, dt, hour, created_at FROM `test`
2020-12-13 07:53:48.844 +0000 [INFO] (0001:preview): > 0.00 seconds
+--------+-------------+----------------+
| id:int | name:string | email:string   |
+--------+-------------+----------------+
|     1  |        aaa  | [email protected] |
|     2  |        bbb  | [email protected] |
|     3  |        ccc  | [email protected] |
+--------+-------------+----------------+

여기에 문제가 있으면 config.yml을 수정하고 다시 확인하십시오.

문제가 없으면 다음 명령으로 Embulk 실행
$ embulk run config.yml

embulk-test_db2_1로 전송되었는지 확인
mysql> select * from test;

+----+------+----------------+
| id | name | email          |
+----+------+----------------+
|  1 | aaa  | [email protected] |
|  2 | bbb  | [email protected] |
|  3 | ccc  | [email protected] |
+----+------+----------------+
3 rows in set (0.00 sec)

확실히!

filter 기능



filter를 사용하면 컬럼의 추가, 형 캐스트 ​​등 여러 가지가 있습니다.
예를 들어 특정 열을 결합하려면 embulk-filter-concat를 사용하여 구성 파일을 다음과 같이 변경하십시오.

embulk/config.yml
in:
  type: mysql
  host: embulk-test_db1_1
  user: user
  password: password
  database: sample_db
  table: test
  select: id, name, email

filters:
- type: concat
  name: namemail
  columns:
  - {name: name}
  - {name: email}

out:
  type: mysql
  host: embulk-test_db2_1
  user: user
  password: password
  database: sample_db
  table: test
  mode: replace

위의 예에서는 name과 email을 연결하여 새 namemail이라는 열을 만듭니다.
$ embulk preview config.yml 

2020-12-13 07:53:45.496 +0000: Embulk v0.9.23
2020-12-13 07:53:46.237 +0000 [WARN] (main): DEPRECATION: JRuby org.jruby.embed.ScriptingContainer is directly 
....

+--------+-------------+----------------+--------------------+
| id:int | name:string | email:string   |  namemail:string   |
+--------+-------------+----------------+--------------------+
|     1  |        aaa  | [email protected] | aaa [email protected] |
|     2  |        bbb  | [email protected] | bbb [email protected] |
|     3  |        ccc  | [email protected] | ccc [email protected] |
+--------+-------------+----------------+--------------------+

그 밖에도 많은 플러그인이 있지만, 여기 Embulk (엠벌크) 플러그인 요약 에 세세하게 정리되어 있으므로, 여기서는 생략한다.

요약



이번에는 mysql간의 데이터 전송을 시도했지만 이종간의 데이터 전송도 간단하게 할 수있어서 매우 편리했습니다.

참고



Embulk
Embulk (엠벌크) 플러그인 요약

좋은 웹페이지 즐겨찾기