PostgreSQL๊ณผ MySQL ๊ฐ„์˜ ๊ต์ฐจ ๋ณต์ œ

PostgreSQL๊ณผ MySQL ๊ฐ„์˜ ๊ต์ฐจ ๋ณต์ œ

PostgreSQL๊ณผ MySQL ๊ฐ„์˜ ๊ต์ฐจ ๋ณต์ œ์™€ ๋‘ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„ ๊ฐ„์˜ ๊ต์ฐจ ๋ณต์ œ๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๊ฐ„๋žตํ•˜๊ฒŒ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ๊ต์ฐจ ๋ณต์ œ๋œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋™์ข… ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ผ๊ณ  ํ•˜๋ฉฐ ์ด๋Š” ํ•œ RDBMS ์„œ๋ฒ„์—์„œ ๋‹ค๋ฅธ RDBMS ์„œ๋ฒ„๋กœ ์ด๋™ํ•˜๋Š” ํŽธ๋ฆฌํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

PostgreSQL ๋ฐ MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๊ด€๊ณ„ํ˜•์œผ๋กœ ๊ฐ„์ฃผ๋˜์ง€๋งŒ ์ถ”๊ฐ€ ํ™•์žฅ์„ ํ†ตํ•ด NoSQL ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—์„œ๋Š” ๊ด€๊ณ„ํ˜• DBMS ๊ด€์ ์—์„œ PostgreSQL๊ณผ MySQL ๊ฐ„์˜ ๋ณต์ œ์— ๋Œ€ํ•ด ๋…ผ์˜ํ•ฉ๋‹ˆ๋‹ค.

์ „์ฒด ๋‚ด๋ถ€ ์ž‘์—…์„ ์„ค๋ช…ํ•˜์ง€๋Š” ์•Š๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„ ๊ฐ„ ๋ณต์ œ ๊ตฌ์„ฑ, ์žฅ์ , ์ œํ•œ ์‚ฌํ•ญ ๋ฐ ์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋Œ€ํ•œ ์•„์ด๋””์–ด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋„๋ก ๊ธฐ๋ณธ ์›์น™๋งŒ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ ๋‘ ๊ฐœ์˜ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„ ๊ฐ„์˜ ๋ณต์ œ๋Š” ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ชจ๋“œ์—์„œ ์ˆ˜ํ–‰๋˜๊ฑฐ๋‚˜ ๋งˆ์Šคํ„ฐ(๊ฒŒ์‹œ์ž, ๋งˆ์Šคํ„ฐ ๋˜๋Š” ํ™œ์„ฑ)์™€ ์Šฌ๋ ˆ์ด๋ธŒ(๊ตฌ๋…์ž, ๋Œ€๊ธฐ ๋˜๋Š” ์ˆ˜๋™) ๊ฐ„์˜ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ๋ณต์ œ์˜ ๋ชฉ์ ์€ ์Šฌ๋ ˆ์ด๋ธŒ ์ธก์— ๋งˆ์Šคํ„ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์‹ค์‹œ๊ฐ„ ๋ณต์‚ฌ๋ณธ์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๋ณต์ œ๊ฐ€ ํ•œ ๋ฐฉํ–ฅ์œผ๋กœ๋งŒ ์ด๋ฃจ์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ์ดํ„ฐ๊ฐ€ ๋งˆ์Šคํ„ฐ์—์„œ ์Šฌ๋ ˆ์ด๋ธŒ๋กœ, ์ฆ‰ ์•กํ‹ฐ๋ธŒ์—์„œ ํŒจ์‹œ๋ธŒ๋กœ ์ „์†ก๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‘ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ„์— ์–‘๋ฐฉํ–ฅ์œผ๋กœ ๋ณต์ œ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ํ™œ์„ฑ-ํ™œ์„ฑ ๊ตฌ์„ฑ์—์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ์Šฌ๋ ˆ์ด๋ธŒ์—์„œ ๋งˆ์Šคํ„ฐ๋กœ ์ „์†ก๋ฉ๋‹ˆ๋‹ค. ๊ณ„๋‹จ์‹ ๋ณต์ œ๋ฅผ ํฌํ•จํ•œ ์ด ๋ชจ๋“  ๊ฒƒ์€ ๋‘˜ ์ด์ƒ์˜ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„ ๊ฐ„์— ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์•กํ‹ฐ๋ธŒ-์•กํ‹ฐ๋ธŒ ๋˜๋Š” ์•กํ‹ฐ๋ธŒ-ํŒจ์‹œ๋ธŒ ๊ตฌ์„ฑ์€ ํ•„์š”, ์ดˆ๊ธฐ ๊ตฌ์„ฑ์—์„œ์˜ ํ•ด๋‹น ๊ธฐ๋Šฅ์˜ ๊ฐ€์šฉ์„ฑ ๋˜๋Š” ์™ธ๋ถ€ ๊ตฌ์„ฑ ์†”๋ฃจ์…˜์˜ ์‚ฌ์šฉ ๋ฐ ๊ธฐ์กด ์žฅ๋‹จ์ ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

์„ค๋ช…๋œ ๊ตฌ์„ฑ์€ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„ ๊ฐ„์— ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„์˜ ๋ณต์ œ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„๋“ค์ด๊ณ  ๋ณต์ œ๋œ ๋ฐ์ดํ„ฐ์˜ ์‹ค์‹œ๊ฐ„ ์Šค๋ƒ…์ƒท์„ ๊ณ„์† ์œ ์ง€ํ•˜๋„๋ก ์„œ๋ฒ„๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. MySQL ๋ฐ PostgreSQL์€ ๋ฐ”์ด๋„ˆ๋ฆฌ ๋กœ๊ทธ ๋ฐฉ๋ฒ•, ๋””์Šคํฌ ์ž ๊ธˆ, ๋ช…๋ น๋ฌธ ๋ฐ ํ–‰ ๊ธฐ๋ฐ˜ ๋ฐฉ๋ฒ•์„ ํฌํ•จํ•˜์—ฌ ์ด๋Ÿฌํ•œ ๊ตฌ์„ฑ์˜ ๋Œ€๋ถ€๋ถ„์„ ๋‚ด๋ถ€ ๋˜๋Š” ํƒ€์‚ฌ ํ™•์žฅ์„ ํ†ตํ•ด ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

ํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„์—์„œ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„๋กœ ์ผํšŒ์„ฑ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด MySQL๊ณผ PostgreSQL ๊ฐ„์˜ ๊ต์ฐจ ๋ณต์ œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์ง์ ‘ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ๊ตํ™˜์„ ์„ค์ •ํ•˜๋ ค๋ฉด pg_chameleon๊ณผ ๊ฐ™์€ ์™ธ๋ถ€ ์˜คํ”ˆ ์†Œ์Šค ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

pg_chameleon์ด ๋ฌด์—‡์ธ๊ฐ€์š”?

pg_chameleon์€ Python 3์˜ MySQL์—์„œ PostgreSQL๋กœ์˜ ๋ณต์ œ ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค. Python์—์„œ๋„ ์˜คํ”ˆ ์†Œ์Šค mysql-replication ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ–‰ ์ด๋ฏธ์ง€๋Š” MySQL ํ…Œ์ด๋ธ”์—์„œ ์ถ”์ถœ๋˜์–ด PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— JSONB ๊ฐœ์ฒด๋กœ ์ €์žฅ๋œ ํ›„ pl/pgsql ํ•จ์ˆ˜๋กœ ํ•ด๋…๋˜์–ด PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์žฌ์ƒ๋ฉ๋‹ˆ๋‹ค.

pg_chameleon์˜ ํŠน์ง•

๋™์ผํ•œ ํด๋Ÿฌ์Šคํ„ฐ์˜ ์—ฌ๋Ÿฌ MySQL ์Šคํ‚ค๋งˆ๋ฅผ ์ผ๋Œ€๋‹ค ๊ตฌ์„ฑ์œผ๋กœ ๋‹จ์ผ ๋Œ€์ƒ PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ณต์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์†Œ์Šค ๋ฐ ๋Œ€์ƒ ์Šคํ‚ค๋งˆ ์ด๋ฆ„์€ ๋™์ผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
๋‹ค๋‹จ๊ณ„ MySQL ๋ณต์ œ๋ณธ์—์„œ ๋ณต์ œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋ณต์ œํ•  ์ˆ˜ ์—†๊ฑฐ๋‚˜ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ํ…Œ์ด๋ธ”์€ ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค.
๊ฐ ๋ณต์ œ ๊ธฐ๋Šฅ์€ ๋ฐ๋ชฌ์— ์˜ํ•ด ์ œ์–ด๋ฉ๋‹ˆ๋‹ค.
YAML ๊ธฐ๋ฐ˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ฐ ๊ตฌ์„ฑ ํŒŒ์ผ์„ ํ†ตํ•ด ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ

์ฃผ์ธ
vm1
vm2

OS ๋ฒ„์ „
CentOS ๋ฆฌ๋ˆ…์Šค 7.6 x86_64
CentOS ๋ฆฌ๋ˆ…์Šค 7.5 x86_64

DB ์„œ๋ฒ„ ๋ฒ„์ „
MySQL์˜ 5.7.26
PostgreSQL 10.5

DB ํฌํŠธ
3306
5433

IP ์ฃผ์†Œ
192.168.56.102
192.168.56.106

์‹œ์ž‘ํ•˜๋ ค๋ฉด pg_chameleon์„ ์„ค์น˜ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ค€๋น„ํ•˜์‹ญ์‹œ์˜ค. ์ด ์˜ˆ์ œ์—์„œ๋Š” ๊ฐ€์ƒ ํ™˜๊ฒฝ์„ ์ƒ์„ฑํ•˜๊ณ  ํ™œ์„ฑํ™”ํ•˜๋Š” Python 3.6.8์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

$> wget https://www.python.org/ftp/python/3.6.8/Python-3.6.8.tar.xz
$> tar -xJf Python-3.6.8.tar.xz
$> cd Python-3.6.8
$> ./configure --enable-optimizations
$> make altinstall

Python3.6์„ ์„ฑ๊ณต์ ์œผ๋กœ ์„ค์น˜ํ•œ ํ›„์—๋Š” ๊ฐ€์ƒ ํ™˜๊ฒฝ ์ƒ์„ฑ ๋ฐ ํ™œ์„ฑํ™”์™€ ๊ฐ™์€ ๋‚˜๋จธ์ง€ ์š”๊ตฌ ์‚ฌํ•ญ์„ ์™„๋ฃŒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ pip ๋ชจ๋“ˆ์ด ์ตœ์‹  ๋ฒ„์ „์œผ๋กœ ์—…๋ฐ์ดํŠธ๋˜์–ด pg_chameleon์„ ์„ค์น˜ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์•„๋ž˜ ๋ช…๋ น์€ ์ตœ์‹  ๋ฒ„์ „์ด 2.0.9์ด์ง€๋งŒ ์˜๋„์ ์œผ๋กœ pg_chameleon 2.0.10๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์—…๋ฐ์ดํŠธ๋œ ๋ฒ„์ „์—์„œ ์ƒˆ๋กœ์šด ๋ฒ„๊ทธ๋ฅผ ๋ฐฉ์ง€ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

$> python3.6 -m venv venv
$> source venv/bin/activate
(venv) $> pip install pip --upgrade
(venv) $> pip install pg_chameleon==2.0.9

๊ทธ๋Ÿฐ ๋‹ค์Œ set_configuration_files ์ธ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ pg_chameleon(์นด๋ฉœ๋ ˆ์˜จ์€ ๋ช…๋ น)์„ ํ˜ธ์ถœํ•˜์—ฌ pg_chameleon์„ ํ™œ์„ฑํ™”ํ•˜๊ณ  ๊ธฐ๋ณธ ๋””๋ ‰ํ„ฐ๋ฆฌ์™€ ๊ตฌ์„ฑ ํŒŒ์ผ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

(venv) $> chameleon set_configuration_files
creating directory /root/.pg_chameleon
creating directory /root/.pg_chameleon/configuration/
creating directory /root/.pg_chameleon/logs/
creating directory /root/.pg_chameleon/pid/
copying configuration  example in /root/.pg_chameleon/configuration//config-example.yml

์ด์ œ ๊ธฐ๋ณธ ๊ตฌ์„ฑ ํŒŒ์ผ์ด ๋˜๋„๋ก config-example.yml์˜ ๋ณต์‚ฌ๋ณธ์„ default.yml๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ์˜ˆ์— ๋Œ€ํ•œ ์ƒ˜ํ”Œ ๊ตฌ์„ฑ ํŒŒ์ผ์ด ์•„๋ž˜์— ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

$> cat default.yml
---
#global settings
pid_dir: '~/.pg_chameleon/pid/'
log_dir: '~/.pg_chameleon/logs/'
log_dest: file
log_level: info
log_days_keep: 10
rollbar_key: ''
rollbar_env: ''

# type_override allows the user to override the default type conversion into a different one.
type_override:
  "tinyint(1)":
    override_to: boolean
    override_tables:
      - "*"

#postgres  destination connection
pg_conn:
  host: "192.168.56.106"
  port: "5433"
  user: "usr_replica"
  password: "pass123"
  database: "db_replica"
  charset: "utf8"

sources:
  mysql:
    db_conn:
      host: "192.168.56.102"
      port: "3306"
      user: "usr_replica"
      password: "pass123"
      charset: 'utf8'
      connect_timeout: 10
    schema_mappings:
      world_x: pgworld_x
    limit_tables:
#      - delphis_mediterranea.foo
    skip_tables:
#      - delphis_mediterranea.bar
    grant_select_to:
      - usr_readonly
    lock_timeout: "120s"
    my_server_id: 100
    replica_batch_size: 10000
    replay_max_rows: 10000
    batch_retention: '1 day'
    copy_max_memory: "300M"
    copy_mode: 'file'
    out_dir: /tmp
    sleep_loop: 1
    on_error_replay: continue
    on_error_read: continue
    auto_maintenance: "disabled"
    gtid_enable: No
    type: mysql
    skip_events:
      insert:
        - delphis_mediterranea.foo #skips inserts on the table delphis_mediterranea.foo
      delete:
        - delphis_mediterranea #skips deletes on schema delphis_mediterranea
      update:

์ด ์˜ˆ์ œ์˜ ๊ตฌ์„ฑ ํŒŒ์ผ์€ ์†Œ์Šค ๋ฐ ๋Œ€์ƒ ํ™˜๊ฒฝ์— ๋งž๊ฒŒ ์•ฝ๊ฐ„ ์ˆ˜์ •๋œ ์ƒ˜ํ”Œ pg_chameleon ํŒŒ์ผ์ด๋ฉฐ, ์•„๋ž˜๋Š” ๊ตฌ์„ฑ ํŒŒ์ผ์˜ ๋‹ค์–‘ํ•œ ์„น์…˜์— ๋Œ€ํ•œ ๊ฐœ์š”์ž…๋‹ˆ๋‹ค.

default.yml ๊ตฌ์„ฑ ํŒŒ์ผ์—๋Š” ์ž ๊ธˆ ํŒŒ์ผ ์œ„์น˜, ๋กœ๊ทธ ์œ„์น˜, ๋กœ๊ทธ ์ €์žฅ ๊ธฐ๊ฐ„ ๋“ฑ๊ณผ ๊ฐ™์€ ์„ค์ •์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์ „์—ญ ์„ค์ • ์„น์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ ์œ ํ˜• ์žฌ์ •์˜ ์„น์…˜์ž…๋‹ˆ๋‹ค. ๋ณต์ œ ์ค‘์— ์œ ํ˜•์„ ์žฌ์ •์˜ํ•˜๊ธฐ ์œ„ํ•œ ๊ทœ์น™ ์ง‘ํ•ฉ์ž…๋‹ˆ๋‹ค. ์ด ์˜ˆ์ œ์—์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœtinyint(1)์„ ๋ถ€์šธ ๊ฐ’์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์œ ํ˜• ์žฌ์ •์˜ ๊ทœ์น™์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ์„น์…˜์—์„œ๋Š” ๋Œ€์ƒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋Œ€ํ•œ ์—ฐ๊ฒฐ ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ์˜ ๊ฒฝ์šฐ ์ด๋Š” pg_conn์œผ๋กœ ์ง€์ •๋œ PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ž…๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰ ์„น์…˜์—์„œ๋Š” ์†Œ์Šค ๋ฐ์ดํ„ฐ, ์ฆ‰ ์†Œ์Šค ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์—ฐ๊ฒฐ ๋งค๊ฐœ ๋ณ€์ˆ˜, ์†Œ์Šค ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ๋Œ€์ƒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ„์˜ ๋งคํ•‘ ๋ฐฉ์‹, ๊ฑด๋„ˆ๋›ฐ์–ด์•ผ ํ•˜๋Š” ํ…Œ์ด๋ธ”, ๋Œ€๊ธฐ ์‹œ๊ฐ„, ๋ฉ”๋ชจ๋ฆฌ, ํŒจํ‚ค์ง€ ํฌ๊ธฐ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. "์†Œ์Šค"๋Š” ๋ณต์ˆ˜ํ˜•์ž…๋‹ˆ๋‹ค. ์ฆ‰, ๋‹จ์ผ ๋Œ€์ƒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์—ฌ๋Ÿฌ ์†Œ์Šค ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋‹ค๋Œ€์ผ ๊ตฌ์„ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

์˜ˆ์ œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค world_x์—๋Š” MySQL ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ์˜ˆ์ œ๋กœ ์ œ๊ณตํ•˜๋Š” ํ–‰์ด ํฌํ•จ๋œ 4๊ฐœ์˜ ํ…Œ์ด๋ธ”์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์šด๋กœ๋“œ ๊ฐ€๋Šฅ ์—ฌ๊ธฐ์—. ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ํ–‰ ์ƒ์„ฑ ๋ฐ ๊ฐ€์ ธ์˜ค๊ธฐ ์ง€์นจ์ด ํฌํ•จ๋œ tar ๋ฐ ์••์ถ• ์•„์นด์ด๋ธŒ๋กœ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

MySQL ๋ฐ PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ๋Š” usr_replica๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ํŠน์ˆ˜ ์‚ฌ์šฉ์ž๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. MySQL์—์„œ๋Š” ๋ณต์ œ๋œ ๋ชจ๋“  ํ…Œ์ด๋ธ”์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์ฝ๊ธฐ ๊ถŒํ•œ์ด ๋ถ€์—ฌ๋ฉ๋‹ˆ๋‹ค.

mysql> CREATE USER usr_replica ;
mysql> SET PASSWORD FOR usr_replica='pass123';
mysql> GRANT ALL ON world_x.* TO 'usr_replica';
mysql> GRANT RELOAD ON *.* to 'usr_replica';
mysql> GRANT REPLICATION CLIENT ON *.* to 'usr_replica';
mysql> GRANT REPLICATION SLAVE ON *.* to 'usr_replica';
mysql> FLUSH PRIVILEGES;

PostgreSQL ์ธก์—์„œ๋Š” MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ํ—ˆ์šฉํ•˜๋Š” db_replica ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. PostgreSQL์˜ usr_replica ์‚ฌ์šฉ์ž๋Š” ์‹ค์ œ ๋ณต์ œ๋œ ํ…Œ์ด๋ธ”๊ณผ ๋ณต์ œ ๋””๋ ‰ํ„ฐ๋ฆฌ ํ…Œ์ด๋ธ”์ด ๊ฐ๊ฐ ํฌํ•จ๋œ ๋‘ ์Šคํ‚ค๋งˆ pgworld_x ๋ฐ sch_chameleon์˜ ์†Œ์œ ์ž๋กœ ์ž๋™ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. create_replica_schema ์ธ์ˆ˜๋Š” ์•„๋ž˜์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด ์ž๋™ ๊ตฌ์„ฑ์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

postgres=# CREATE USER usr_replica WITH PASSWORD 'pass123';
CREATE ROLE
postgres=# CREATE DATABASE db_replica WITH OWNER usr_replica;
CREATE DATABASE

MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๋ณต์ œ๋ฅผ ์ค€๋น„ํ•˜๊ธฐ ์œ„ํ•ด ์ผ๋ถ€ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ณ€๊ฒฝ์œผ๋กœ ๊ตฌ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ ์šฉํ•˜๋ ค๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„๋ฅผ ๋‹ค์‹œ ์‹œ์ž‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

$> vi /etc/my.cnf
binlog_format= ROW
binlog_row_image=FULL
log-bin = mysql-bin
server-id = 1

์ด์ œ pg_chameleon ๋ช…๋ น์„ ์‹คํ–‰ํ•  ๋•Œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ๋‘ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„์— ๋Œ€ํ•œ ์—ฐ๊ฒฐ์„ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

PostgreSQL ๋…ธ๋“œ์—์„œ:

$> mysql -u usr_replica -Ap'admin123' -h 192.168.56.102 -D world_x

MySQL ๋…ธ๋“œ์—์„œ:

$> psql -p 5433 -U usr_replica -h 192.168.56.106 db_replica

๋‹ค์Œ ์„ธ ๊ฐ€์ง€ pg_chameleon(์นด๋ฉœ๋ ˆ์˜จ) ๋ช…๋ น์€ ํ™˜๊ฒฝ์„ ์ค€๋น„ํ•˜๊ณ , ์†Œ์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ , ๋ณต์ œ๋ณธ์„ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค. pg_chameleon์— ๋Œ€ํ•œ create_replica_schema ์ธ์ˆ˜๋Š” ์ด๋ฏธ ์„ค๋ช…ํ•œ ๋Œ€๋กœ PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๊ธฐ๋ณธ ์Šคํ‚ค๋งˆ(sch_chameleon)์™€ ๋ณต์ œ ์Šคํ‚ค๋งˆ(pgworld_x)๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. add_source ์ธ์ˆ˜๋Š” ๊ตฌ์„ฑ ํŒŒ์ผ(default.yml)์„ ์ฝ์–ด ๊ตฌ์„ฑ์— ์†Œ์Šค ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š”๋ฐ, ์šฐ๋ฆฌ์˜ ๊ฒฝ์šฐ์—๋Š” mysql์ด๊ณ  init_replica๋Š” ๊ตฌ์„ฑ ํŒŒ์ผ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์„ฑ์„ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.

$> chameleon create_replica_schema --debug
$> chameleon add_source --config default --source mysql --debug
$> chameleon init_replica --config default --source mysql --debug

์ด ์„ธ ๊ฐ€์ง€ ๋ช…๋ น์˜ ์ถœ๋ ฅ์€ ์„ฑ๊ณต์ ์œผ๋กœ ์‹คํ–‰๋˜์—ˆ์Œ์„ ๋ถ„๋ช…ํžˆ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ถฉ๋Œ์ด๋‚˜ ๊ตฌ๋ฌธ ์˜ค๋ฅ˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ํžŒํŠธ์™€ ํ•จ๊ป˜ ๊ฐ„๋‹จํ•˜๊ณ  ๋ช…ํ™•ํ•œ ๋ฉ”์‹œ์ง€๋กœ ๋ณด๊ณ ๋ฉ๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ start_replica๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณต์ œ๋ฅผ ์‹œ์ž‘ํ•˜๊ณ  ์„ฑ๊ณต ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค.

$> chameleon start_replica --config default --source mysql 
output: Starting the replica process for source mysql

show_status ์ธ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณต์ œ ์ƒํƒœ๋ฅผ ์ฟผ๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ show_errors ์ธ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์˜ค๋ฅ˜๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ ๊ฒฐ๊ณผ.

์ด๋ฏธ ๋งํ–ˆ๋“ฏ์ด ๊ฐ ๋ณต์ œ ๊ธฐ๋Šฅ์€ ๋ฐ๋ชฌ์— ์˜ํ•ด ์ œ์–ด๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ณด๋ ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด Linux ps ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ์„ธ์Šค ํ…Œ์ด๋ธ”์„ ์ฟผ๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๊ทธ ๊ฒฐ๊ณผ.

์•„๋ž˜์™€ ๊ฐ™์ด ์‹ค์‹œ๊ฐ„์œผ๋กœ ํ…Œ์ŠคํŠธํ•  ๋•Œ๊นŒ์ง€ ๋ณต์ œ๋Š” ๊ตฌ์„ฑ๋œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•˜๊ณ  ๋ช‡ ๊ฐœ์˜ ๋ ˆ์ฝ”๋“œ๋ฅผ MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์‚ฝ์ž…ํ•œ ๋‹ค์Œ pg_chameleon์—์„œ sync_tables ์ธ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋ฐ๋ชฌ์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ๋ ˆ์ฝ”๋“œ๊ฐ€ ํฌํ•จ๋œ ํ…Œ์ด๋ธ”์„ PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ณต์ œํ•ฉ๋‹ˆ๋‹ค.

mysql> create table t1 (n1 int primary key, n2 varchar(10));
Query OK, 0 rows affected (0.01 sec)
mysql> insert into t1 values (1,'one');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t1 values (2,'two');
Query OK, 1 row affected (0.00 sec)

$> chameleon sync_tables --tables world_x.t1 --config default --source mysql
Sync tables process for source mysql started.

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ํ…Œ์ด๋ธ”์„ ์ฟผ๋ฆฌํ•˜๊ณ  ํ–‰์„ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

$> psql -p 5433 -U usr_replica -d db_replica -c "select * from pgworld_x.t1";
 n1 |  n2
----+-------
  1 | one
  2 | two

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ ๋‹ค์Œ pg_chameleon ๋ช…๋ น์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์ด ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ๋Œ€์ƒ ํ…Œ์ด๋ธ”์˜ ํ–‰์ด ๋ณต์ œ๋˜์—ˆ์Œ์„ ํ™•์ธํ•œ ํ›„์— ๋ช…๋ น์„ ์‹คํ–‰ํ•ด์•ผ ํ•˜๋ฉฐ, ๊ทธ ๊ฒฐ๊ณผ ์›๋ณธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋˜๋Š” ๋ณต์ œ ์ฒด๊ณ„(sch_chameleon)๋ฅผ ์ฐธ์กฐํ•˜์ง€ ์•Š๊ณ  ๊น”๋”ํ•˜๊ฒŒ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜๋œ PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

$> chameleon stop_replica --config default --source mysql 
$> chameleon detach_replica --config default --source mysql --debug

์›ํ•˜๋Š” ๊ฒฝ์šฐ ๋‹ค์Œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ์›๋ž˜ ๊ตฌ์„ฑ ๋ฐ ๋ณต์ œ ์ฒด๊ณ„๋ฅผ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

$> chameleon drop_source --config default --source mysql --debug
$> chameleon drop_replica_schema --config default --source mysql --debug

pg_chameleon์˜ ์žฅ์ 

๊ฐ„ํŽธํ•œ ์„ค์ • ๋ฐ ๊ตฌ์„ฑ.
๋ช…ํ™•ํ•œ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ํ†ตํ•ด ์ด์ƒ ํ˜„์ƒ์„ ์‰ฝ๊ฒŒ ํ•ด๊ฒฐํ•˜๊ณ  ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋‚˜๋จธ์ง€ ๊ตฌ์„ฑ์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ ๋„ ์ดˆ๊ธฐํ™” ํ›„์— ์ถ”๊ฐ€ ํŠน์ˆ˜ ํ…Œ์ด๋ธ”์„ ๋ณต์ œ์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋‹จ์ผ ๋Œ€์ƒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋Œ€ํ•ด ์—ฌ๋Ÿฌ ์†Œ์Šค ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ด๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹จ์ผ PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋กœ ๊ฒฐํ•ฉํ•˜๋Š” ๊ฒฝ์šฐ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
์„ ํƒํ•œ ํ…Œ์ด๋ธ”์„ ๋ณต์ œํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค.

pg_chameleon์˜ ๋‹จ์ 

์†Œ์Šค๋กœ๋Š” MySQL 5.5 ์ด์ƒ, ๋Œ€์ƒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋กœ๋Š” PostgreSQL 9.5 ์ด์ƒ์—์„œ๋งŒ ์ง€์›๋ฉ๋‹ˆ๋‹ค.
๊ฐ ํ…Œ์ด๋ธ”์—๋Š” ๊ธฐ๋ณธ ํ‚ค ๋˜๋Š” ๊ณ ์œ  ํ‚ค๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด init_replica ํ”„๋กœ์„ธ์Šค ์ค‘์— ํ…Œ์ด๋ธ”์ด ์ดˆ๊ธฐํ™”๋˜์ง€๋งŒ ๋ณต์ œ๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.
๋‹จ๋ฐฉํ–ฅ ๋ณต์ œ - MySQL์—์„œ PostgreSQL๋กœ๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ "์•กํ‹ฐ๋ธŒ-ํŒจ์‹œ๋ธŒ" ํšŒ๋กœ์—๋งŒ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.
์†Œ์Šค๋Š” MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋งŒ ๊ฐ€๋Šฅํ•˜๋ฉฐ PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์†Œ์Šค๋กœ ์ง€์›ํ•˜๋Š” ๊ฒƒ์€ ์‹คํ—˜์ ์ด๋ฉฐ ์ œํ•œ์ด ์žˆ์Šต๋‹ˆ๋‹ค(์ž์„ธํžˆ ์•Œ์•„๋ณด๊ธฐ) ์—ฌ๊ธฐ์—)

pg_chameleon์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ

pg_chameleon์˜ ๋ณต์ œ ๋ฐฉ๋ฒ•์€ MySQL์—์„œ PostgreSQL๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋Š” ๋ฐ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ์ค‘์š”ํ•œ ๋‹จ์ ์€ ๋ณต์ œ๊ฐ€ ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ๋งŒ ์ˆ˜ํ–‰๋˜๋ฏ€๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ „๋ฌธ๊ฐ€๊ฐ€ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ด์™ธ์˜ ์šฉ๋„๋กœ ๋ณต์ œ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋ฅผ ์›ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‹จ๋ฐฉํ–ฅ ๋ณต์ œ ๋ฌธ์ œ๋Š” ๋˜ ๋‹ค๋ฅธ ์˜คํ”ˆ ์†Œ์Šค ๋„๊ตฌ์ธ SymmetricDS๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ณต์‹ ๋ฌธ์„œ์—์„œ ์ž์„ธํ•œ ๋‚ด์šฉ์„ ์ฝ์–ด๋ณด์„ธ์š”. ์—ฌ๊ธฐ์—. ๋ช…๋ น์ค„ ๋„์›€๋ง์„ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—.

SymmetricDS ๊ฐœ์š”

SymmetricDS๋Š” Oracle, MongoDB, PostgreSQL, MySQL, SQL Server, MariaDB, DB2, Sybase, Greenplum, Informix, H2, Firebird ๋ฐ ๊ธฐํƒ€ ํด๋ผ์šฐ๋“œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ธ์Šคํ„ด์Šค(์˜ˆ: Redshift)์™€ ๊ฐ™์€ ๋‹ค๋ฅธ ์ผ๋ฐ˜์ ์ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋ณต์ œํ•˜๋Š” ์˜คํ”ˆ ์†Œ์Šค ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. Azure ๋“ฑ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ธฐ๋Šฅ: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐ ํŒŒ์ผ ๋™๊ธฐํ™”, ๋‹ค์ค‘ ๋งˆ์Šคํ„ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ณต์ œ, ํ•„ํ„ฐ๋ง๋œ ๋™๊ธฐํ™”, ๋ณ€ํ™˜ ๋“ฑ. ์ด๋Š” Java ๋„๊ตฌ์ด๋ฉฐ JRE ๋˜๋Š” JDK(๋ฒ„์ „ 8.0 ์ด์ƒ)์˜ ํ‘œ์ค€ ๋ฆด๋ฆฌ์Šค๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์†Œ์Šค ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ํŠธ๋ฆฌ๊ฑฐ์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๊ธฐ๋กํ•˜๊ณ  ๋ฐฐ์น˜ ํ˜•ํƒœ๋กœ ํ•ด๋‹น ๋Œ€์ƒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋Œ€์นญDS ๊ธฐ๋Šฅ

์ด ๋„๊ตฌ๋Š” ํ”Œ๋žซํผ ๋…๋ฆฝ์ ์ž…๋‹ˆ๋‹ค. ์ฆ‰, ๋‘ ๊ฐœ ์ด์ƒ์˜ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ตํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ๊ธฐ๋ก์„ ์‚ฌ์šฉํ•˜์—ฌ ๋™๊ธฐํ™”๋˜๋Š” ๋ฐ˜๋ฉด, ํŒŒ์ผ ์‹œ์Šคํ…œ ๊ธฐ๋ฐ˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ํŒŒ์ผ ๋™๊ธฐํ™”๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
์ผ๋ จ์˜ ๊ทœ์น™์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š” Push ๋ฐ Pull ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•œ ์–‘๋ฐฉํ–ฅ ๋ณต์ œ์ž…๋‹ˆ๋‹ค.
์•ˆ์ „ํ•œ ์ €๋Œ€์—ญํญ ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ ์ „์†ก์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
์žฅ์•  ํ›„ ๋…ธ๋“œ๊ฐ€ ์ž‘๋™์„ ์žฌ๊ฐœํ•  ๋•Œ ์ž๋™ ๋ณต๊ตฌ ๋ฐ ์ž๋™ ์ถฉ๋Œ ํ•ด๊ฒฐ.
ํด๋ผ์šฐ๋“œ์™€ ํ˜ธํ™˜๋˜๊ณ  ๊ฐ•๋ ฅํ•œ ํ™•์žฅ API.

์˜ˆ

SymmetricDS๋Š” ๋‹ค์Œ ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋‘ ์Šฌ๋ ˆ์ด๋ธŒ(์ž์‹) ๋…ธ๋“œ ๊ฐ„์˜ ๋ฐ์ดํ„ฐ ๋ณต์ œ๋ฅผ ์ค‘์•™์—์„œ ์กฐ์ •ํ•˜๋Š” ๋งˆ์Šคํ„ฐ(์ƒ์œ„) ๋…ธ๋“œ์ด๋ฉฐ, ํ•˜์œ„ ๋…ธ๋“œ ๊ฐ„์˜ ํ†ต์‹ ์€ ์ƒ์œ„๋ฅผ ํ†ตํ•ด์„œ๋งŒ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
ํ™œ์„ฑ ๋…ธ๋“œ(๋…ธ๋“œ 1)๋Š” ์ค‘๊ฐœ์ž ์—†์ด ๋‹ค๋ฅธ ํ™œ์„ฑ ๋…ธ๋“œ(๋…ธ๋“œ 2)์™€ ๋ณต์ œ๋ฅผ ์œ„ํ•ด ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‘ ์˜ต์…˜ ๋ชจ๋‘ ํ‘ธ์‹œ ๋ฐ ํ’€์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ ๊ตํ™˜์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด ์˜ˆ์—์„œ๋Š” ํ™œ์„ฑ-ํ™œ์„ฑ ๊ตฌ์„ฑ์„ ๊ณ ๋ คํ•ฉ๋‹ˆ๋‹ค. ์ „์ฒด ์•„ํ‚คํ…์ฒ˜๋ฅผ ์„ค๋ช…ํ•˜๋ ค๋ฉด ์‹œ๊ฐ„์ด ๋„ˆ๋ฌด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋ฏ€๋กœ ์กฐ์‚ฌํ•ด ๋ณด์„ธ์š”. ์ง€๋„๋ ฅSymmetricDS ์žฅ์น˜์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณด์„ธ์š”.

SymmetricDS ์„ค์น˜๋Š” ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. zip ํŒŒ์ผ์˜ ์˜คํ”ˆ ์†Œ์Šค ๋ฒ„์ „์„ ๋‹ค์šด๋กœ๋“œํ•˜์„ธ์š”. ๋”ฐ๋ผ์„œ ๊ทธ๋ฆฌ๊ณ  ์›ํ•˜๋Š” ๊ณณ์— ๊บผ๋‚ด๋ณด์„ธ์š”. ์•„๋ž˜ ํ‘œ์—๋Š” ์ด ์˜ˆ์˜ SymmetricDS ์„ค์น˜ ์œ„์น˜ ๋ฐ ๋ฒ„์ „์— ๋Œ€ํ•œ ์ •๋ณด๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋‘ ๋…ธ๋“œ์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฒ„์ „, Linux ๋ฒ„์ „, IP ์ฃผ์†Œ ๋ฐ ํฌํŠธ๋„ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

์ฃผ์ธ
vm1
vm2

OS ๋ฒ„์ „
CentOS ๋ฆฌ๋ˆ…์Šค 7.6 x86_64
CentOS ๋ฆฌ๋ˆ…์Šค 7.6 x86_64

DB ์„œ๋ฒ„ ๋ฒ„์ „
MySQL์˜ 5.7.26
PostgreSQL 10.5

DB ํฌํŠธ
3306
5832

IP ์ฃผ์†Œ
192.168.1.107
192.168.1.112

๋Œ€์นญDS ๋ฒ„์ „
๋Œ€์นญDS 3.9
๋Œ€์นญDS 3.9

๋Œ€์นญDS ์„ค์น˜ ๊ฒฝ๋กœ
/usr/local/๋Œ€์นญ-์„œ๋ฒ„-3.9.20
/usr/local/๋Œ€์นญ-์„œ๋ฒ„-3.9.20

๋Œ€์นญDS ๋…ธ๋“œ ์ด๋ฆ„
๊ธฐ์—…-000
์ƒ์ -001

์—ฌ๊ธฐ์„œ๋Š” /usr/local/symmetric-server-3.9.20์— SymmetricDS๋ฅผ ์„ค์น˜ํ•˜๊ณ  ๋‹ค์–‘ํ•œ ํ•˜์œ„ ๋””๋ ‰ํ„ฐ๋ฆฌ์™€ ํŒŒ์ผ์ด ์—ฌ๊ธฐ์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ƒ˜ํ”Œ๊ณผ ์—”์ง„ ํ•˜์œ„ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ๊ด€์‹ฌ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒ˜ํ”Œ ๋””๋ ‰ํ„ฐ๋ฆฌ์—๋Š” ๋น ๋ฅด๊ฒŒ ์‹œ์ž‘ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ์˜ˆ์ œ SQL ์Šคํฌ๋ฆฝํŠธ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋…ธ๋“œ ์†์„ฑ์ด ํฌํ•จ๋œ ์˜ˆ์ œ ๊ตฌ์„ฑ ํŒŒ์ผ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ƒ˜ํ”Œ ๋””๋ ‰ํ„ฐ๋ฆฌ์—๋Š” ๋…ธ๋“œ ์†์„ฑ์ด ํฌํ•จ๋œ ์„ธ ๊ฐ€์ง€ ๊ตฌ์„ฑ ํŒŒ์ผ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฆ„์€ ํŠน์ • ์ฒด๊ณ„์—์„œ ๋…ธ๋“œ์˜ ํŠน์„ฑ์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

corp-000.properties
store-001.properties
store-002.properties

SymmetricDS์—๋Š” ๊ธฐ๋ณธ 3๋…ธ๋“œ ์„ค๊ณ„(์˜ต์…˜ 1)์— ํ•„์š”ํ•œ ๋ชจ๋“  ๊ตฌ์„ฑ ํŒŒ์ผ์ด ์žˆ์œผ๋ฉฐ, 2๋…ธ๋“œ ์„ค๊ณ„(์˜ต์…˜ 2)์—๋„ ๋™์ผํ•œ ํŒŒ์ผ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ๊ตฌ์„ฑ ํŒŒ์ผ์„ ์ƒ˜ํ”Œ ๋””๋ ‰ํ„ฐ๋ฆฌ์—์„œ vm1 ํ˜ธ์ŠคํŠธ์˜ ์—”์ง„์œผ๋กœ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฐํ˜€์กŒ์Šต๋‹ˆ๋‹ค.

$> cat engines/corp-000.properties
engine.name=corp-000
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://192.168.1.107:3306/replica_db?autoReconnect=true&useSSL=false
db.user=root
db.password=admin123
registration.url=
sync.url=http://192.168.1.107:31415/sync/corp-000
group.id=corp
external.id=000

SymmetricDS ๊ตฌ์„ฑ์˜ ์ด ๋…ธ๋“œ๋ฅผ corp-000์ด๋ผ๊ณ  ํ•˜๋ฉฐ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์€ ์œ„์˜ ์—ฐ๊ฒฐ ๋ฌธ์ž์—ด๊ณผ ๋กœ๊ทธ์ธ ์ž๊ฒฉ ์ฆ๋ช…์„ ์‚ฌ์šฉํ•˜๋Š” mysql jdbc ๋“œ๋ผ์ด๋ฒ„์— ์˜ํ•ด ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค. Replica_db ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์—ฐ๊ฒฐํ•˜๋ฉด ์Šคํ‚ค๋งˆ ์ƒ์„ฑ ์ค‘์— ํ…Œ์ด๋ธ”์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. sync.url์€ ๋™๊ธฐํ™”๋ฅผ ์œ„ํ•ด ๋…ธ๋“œ์— ์ ‘์†ํ•  ์œ„์น˜๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

ํ˜ธ์ŠคํŠธ vm2์˜ ๋…ธ๋“œ 2๋Š” store-001๋กœ ๊ตฌ์„ฑ๋˜๊ณ  ๋‚˜๋จธ์ง€๋Š” ์•„๋ž˜ node.properties ํŒŒ์ผ์— ์ง€์ •๋ฉ๋‹ˆ๋‹ค. Node store-001์€ PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‹คํ–‰ํ•˜๊ณ  pgdb_replica๋Š” ๋ณต์ œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ž…๋‹ˆ๋‹ค. Registration.url์„ ์‚ฌ์šฉํ•˜๋ฉด ํ˜ธ์ŠคํŠธ vm2๊ฐ€ ํ˜ธ์ŠคํŠธ vm1์— ์ ‘์†ํ•˜๊ณ  ํ˜ธ์ŠคํŠธ๋กœ๋ถ€ํ„ฐ ๊ตฌ์„ฑ ์„ธ๋ถ€์ •๋ณด๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

$> cat engines/store-001.properties
engine.name=store-001
db.driver=org.postgresql.Driver
db.url=jdbc:postgresql://192.168.1.112:5832/pgdb_replica
db.user=postgres
db.password=admin123
registration.url=http://192.168.1.107:31415/sync/corp-000
group.id=store
external.id=001

์™„์„ฑ๋œ SymmetricDS ์˜ˆ์ œ์—๋Š” ๋‘ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„(๋‘ ๋…ธ๋“œ) ๊ฐ„์˜ ์–‘๋ฐฉํ–ฅ ๋ณต์ œ๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ๋‹จ๊ณ„๋Š” ํ˜ธ์ŠคํŠธ vm1(corp-000)์—์„œ ์ˆ˜ํ–‰๋˜๋ฉฐ, ์ด๋Š” 4๊ฐœ์˜ ํ…Œ์ด๋ธ”์ด ์žˆ๋Š” ์˜ˆ์ œ ์Šคํ‚ค๋งˆ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ Symadmin ๋ช…๋ น์œผ๋กœ create-sym-tables๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋…ธ๋“œ ๊ฐ„ ๋ณต์ œ ๊ทœ์น™๊ณผ ๋ฐฉํ–ฅ์ด ์ €์žฅ๋˜๋Š” ๋””๋ ‰ํ„ฐ๋ฆฌ ํ…Œ์ด๋ธ”์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ๊ฐ€ ํ…Œ์ด๋ธ”์— ๋กœ๋“œ๋ฉ๋‹ˆ๋‹ค.

vm1$> cd /usr/local/symmetric-server-3.9.20/bin
vm1$> ./dbimport --engine corp-000 --format XML create_sample.xml
vm1$> ./symadmin --engine corp-000 create-sym-tables
vm1$> ./dbimport --engine corp-000 insert_sample.sql

์˜ˆ์ œ์—์„œ item ๋ฐ item_ํŒ๋งค_price ํ…Œ์ด๋ธ”์€ corp-000์—์„œ store-001๋กœ ๋ณต์ œ๋˜๋„๋ก ์ž๋™์œผ๋กœ ๊ตฌ์„ฑ๋˜๊ณ , ํŒ๋งค ํ…Œ์ด๋ธ”(sale_transaction ๋ฐ sale_return_line_item)์€ store-001์—์„œ corp-000์œผ๋กœ ๋ณต์ œ๋˜๋„๋ก ์ž๋™์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. ์ด์ œ ํ˜ธ์ŠคํŠธ vm2(store-001)์˜ PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์Šคํ‚ค๋งˆ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ corp-000์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค.

vm2$> cd /usr/local/symmetric-server-3.9.20/bin
vm2$> ./dbimport --engine store-001 --format XML create_sample.xml

vm1์˜ MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์˜ˆ์ œ ํ…Œ์ด๋ธ”๊ณผ SymmetricDS ์นดํƒˆ๋กœ๊ทธ ํ…Œ์ด๋ธ”์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. SymmetricDS ์‹œ์Šคํ…œ ํ…Œ์ด๋ธ”(sym_ ์ ‘๋‘์–ด)์€ ํ˜„์žฌ ๋…ธ๋“œ corp-000์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋…ธ๋“œ corp-001์—์„œ create-sym-tables ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๊ณ  ๋ณต์ œ๋ฅผ ๊ด€๋ฆฌํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋…ธ๋“œ store-4์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ์˜ˆ์ œ ํ…Œ์ด๋ธ”์ด XNUMX๊ฐœ๋งŒ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชจ๋‘. ์•„๋ž˜์™€ ๊ฐ™์ด ๋‘ ๋…ธ๋“œ ๋ชจ๋‘์—์„œ Sym ์„œ๋ฒ„ ํ”„๋กœ์„ธ์Šค๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ํ™˜๊ฒฝ์ด ์ค€๋น„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

vm1$> cd /usr/local/symmetric-server-3.9.20/bin
vm1$> sym 2>&1 &

๋กœ๊ทธ ํ•ญ๋ชฉ์€ SymmetricDS๊ฐ€ ์„ค์น˜๋œ ๋””๋ ‰ํ„ฐ๋ฆฌ์˜ ๋กœ๊ทธ ํด๋”์— ์žˆ๋Š” ๋ฐฑ๊ทธ๋ผ์šด๋“œ ๋กœ๊ทธ ํŒŒ์ผ(symmetric.log)๊ณผ ํ‘œ์ค€ ์ถœ๋ ฅ์œผ๋กœ ์ „์†ก๋ฉ๋‹ˆ๋‹ค. ์ด์ œ ๋…ธ๋“œ store-001์—์„œ Sym ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

vm2$> cd /usr/local/symmetric-server-3.9.20/bin
vm2$> sym 2>&1 &

vm2 ํ˜ธ์ŠคํŠธ์—์„œ Sym ์„œ๋ฒ„ ํ”„๋กœ์„ธ์Šค๋ฅผ ์‹คํ–‰ํ•˜๋ฉด PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— SymmetricDS ์นดํƒˆ๋กœ๊ทธ ํ…Œ์ด๋ธ”๋„ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๋‘ ๋…ธ๋“œ ๋ชจ๋‘์—์„œ Sym ์„œ๋ฒ„ ํ”„๋กœ์„ธ์Šค๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์„œ๋กœ ์กฐ์ •ํ•˜์—ฌ corp-000์—์„œ store-001๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณต์ œํ•ฉ๋‹ˆ๋‹ค. ๋ช‡ ์ดˆ ํ›„์— ์–‘์ชฝ์˜ 4๊ฐœ ํ…Œ์ด๋ธ”์„ ๋ชจ๋‘ ์ฟผ๋ฆฌํ•˜๋ฉด ๋ณต์ œ๊ฐ€ ์„ฑ๊ณตํ•œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜๋Š” ๋‹ค์Œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ corp-001์—์„œ ๋…ธ๋“œ store-000๋กœ ๋ถ€ํŠธ์ŠคํŠธ๋žฉ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

vm1$> ./symadmin --engine corp-000 reload-node 001

์ด ์‹œ์ ์—์„œ ๋…ธ๋“œ corp-000(ํ˜ธ์ŠคํŠธ: vm1)์˜ MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์žˆ๋Š” ํ•ญ๋ชฉ ํ…Œ์ด๋ธ”์— ์ƒˆ ๋ ˆ์ฝ”๋“œ๊ฐ€ ์‚ฝ์ž…๋˜๊ณ , ๋…ธ๋“œ store-001(ํ˜ธ์ŠคํŠธ: vm2)์˜ PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋Œ€ํ•œ ๋ณต์ œ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. corp-000์—์„œ store-001๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ด๋™ํ•˜๋Š” Pull ์ž‘์—…์ด ๋ณด์ž…๋‹ˆ๋‹ค.

mysql> insert into item values ('22000002','Jelly Bean');
Query OK, 1 row affected (0.00 sec)

vm2$> psql -p 5832 -U postgres pgdb_replica -c "select * from item"
 item_id  |   name
----------+-----------
 11000001 | Yummy Gum
 22000002 | Jelly Bean
(2 rows)

store-001์—์„œ corp-000์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ด๋™ํ•˜๋Š” ํ‘ธ์‹œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด sale_transaction ํ…Œ์ด๋ธ”์— ๋ ˆ์ฝ”๋“œ๋ฅผ ์‚ฝ์ž…ํ•˜๊ณ  ๋ณต์ œ๊ฐ€ ์„ฑ๊ณตํ–ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

๊ทธ ๊ฒฐ๊ณผ.

MySQL๊ณผ PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ„์˜ ์˜ˆ์ œ ํ…Œ์ด๋ธ”์˜ ์„ฑ๊ณต์ ์ธ ์–‘๋ฐฉํ–ฅ ๋ณต์ œ ์„ค์ •์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ์ƒˆ ์‚ฌ์šฉ์ž ํ…Œ์ด๋ธ”์— ๋Œ€ํ•œ ๋ณต์ œ๋ฅผ ์„ค์ •ํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ๋”ฐ๋ฅด์„ธ์š”. ์˜ˆ๋ฅผ ๋“ค์–ด ํ…Œ์ด๋ธ” t1์„ ์ƒ์„ฑํ•˜๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณต์ œ ๊ทœ์น™์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์œผ๋กœ corp-000์—์„œ store-001๋กœ์˜ ๋ณต์ œ๋งŒ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

mysql> create table  t1 (no integer);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into sym_channel (channel_id,create_time,last_update_time) 
values ('t1',current_timestamp,current_timestamp);
Query OK, 1 row affected (0.01 sec)

mysql> insert into sym_trigger (trigger_id, source_table_name,channel_id,
last_update_time, create_time) values ('t1', 't1', 't1', current_timestamp,
current_timestamp);
Query OK, 1 row affected (0.01 sec)

mysql> insert into sym_trigger_router (trigger_id, router_id,
Initial_load_order, create_time,last_update_time) values ('t1',
'corp-2-store-1', 1, current_timestamp,current_timestamp);
Query OK, 1 row affected (0.01 sec)

๊ทธ๋Ÿฐ ๋‹ค์Œ ํ…Œ์ด๋ธ” ์ •์˜๋ฅผ ๋งคํ•‘ํ•˜๊ธฐ ์œ„ํ•ด ํŠธ๋ฆฌ๊ฑฐ๋ฅผ ๋‹ค์‹œ ์ƒ์„ฑํ•˜๋Š” sync-triggers ์ธ์ˆ˜์™€ ํ•จ๊ป˜ Symadmin ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ์Šคํ‚ค๋งˆ ๋ณ€๊ฒฝ, ์ฆ‰ ์ƒˆ ํ…Œ์ด๋ธ” ์ถ”๊ฐ€์— ๋Œ€ํ•œ ์•Œ๋ฆผ์„ ๊ตฌ์„ฑ์— ๋ณด๋ƒ…๋‹ˆ๋‹ค. send-schema๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ์Šคํ‚ค๋งˆ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ node store-001๋กœ ๋ณด๋‚ด๊ณ  ํ…Œ์ด๋ธ” t1์˜ ๋ณต์ œ๋ฅผ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

vm1$> ./symadmin -e corp-000 --node=001 sync-triggers    
vm1$> ./symadmin send-schema -e corp-000 --node=001 t1

SymmetricDS์˜ ์ด์ 

XNUMX๋…ธ๋“œ ๋˜๋Š” XNUMX๋…ธ๋“œ ํšŒ๋กœ ์ƒ์„ฑ์„ ์œ„ํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ํฌํ•จ๋œ ๊ธฐ์„ฑ ํŒŒ์ผ ์„ธํŠธ๋ฅผ ํฌํ•จํ•˜์—ฌ ๊ฐ„ํŽธํ•œ ์„ค์น˜ ๋ฐ ๊ตฌ์„ฑ.
์„œ๋ฒ„, ๋…ธํŠธ๋ถ, ๋ชจ๋ฐ”์ผ ์žฅ์น˜๋ฅผ ํฌํ•จํ•œ ํฌ๋กœ์Šค ํ”Œ๋žซํผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐ ํ”Œ๋žซํผ ๋…๋ฆฝ์„ฑ.
๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋กœ์ปฌ, WAN ๋˜๋Š” ํด๋ผ์šฐ๋“œ์˜ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ณต์ œํ•˜์„ธ์š”.
ํŽธ๋ฆฌํ•œ ๋ณต์ œ๋ฅผ ์œ„ํ•ด ๋ช‡ ๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋˜๋Š” ์ˆ˜์ฒœ ๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋กœ ์ตœ์ ์˜ ์ž‘์—…์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
GUI์™€ ํƒ์›”ํ•œ ์ง€์›์„ ๊ฐ–์ถ˜ ์œ ๋ฃŒ ๋ฒ„์ „์ž…๋‹ˆ๋‹ค.

SymmetricDS์˜ ๋‹จ์ 

์นดํƒˆ๋กœ๊ทธ ํ…Œ์ด๋ธ”์„ ๋กœ๋“œํ•˜๋ ค๋ฉด SQL ๋ฌธ์„ ํ†ตํ•ด ๋ช…๋ น์ค„์—์„œ ๋ณต์ œ ๊ทœ์น™๊ณผ ๋ฐฉํ–ฅ์„ ์ˆ˜๋™์œผ๋กœ ์ •์˜ํ•ด์•ผ ํ•˜๋Š”๋ฐ ์ด๋Š” ๋ถˆํŽธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋ณต์ œ ๊ทœ์น™๊ณผ ๋ฐฉํ–ฅ์„ ์ •์˜ํ•˜๋Š” SQL ๋ฌธ์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํ•œ ๋ณต์ œ๋ฅผ ์œ„ํ•ด ๋งŽ์€ ํ…Œ์ด๋ธ”์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์€ ์ง€๋ฃจํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋กœ๊ทธ์— ๊ธฐ๋ก๋˜๋Š” ์ •๋ณด๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์•„ ๊ณต๊ฐ„์„ ๋งŽ์ด ์ฐจ์ง€ํ•˜์ง€ ์•Š๋„๋ก ๋กœ๊ทธ ํŒŒ์ผ์„ ์ •๋ฆฌํ•ด์•ผ ํ•  ๋•Œ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

SymmetricDS์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ

SymmetricDS๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด XNUMX๊ฐœ, XNUMX๊ฐœ ๋˜๋Š” ์ˆ˜์ฒœ ๊ฐœ์˜ ๋…ธ๋“œ ๊ฐ„์— ์–‘๋ฐฉํ–ฅ ๋ณต์ œ๋ฅผ ์„ค์ •ํ•˜์—ฌ ํŒŒ์ผ์„ ๋ณต์ œํ•˜๊ณ  ๋™๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋…ธ๋“œ์—์„œ ์žฅ๊ธฐ๊ฐ„ ๋‹ค์šดํƒ€์ž„์ด ๋ฐœ์ƒํ•œ ํ›„ ์ž๋™ ๋ฐ์ดํ„ฐ ๋ณต๊ตฌ, HTTPS๋ฅผ ํ†ตํ•œ ๋…ธ๋“œ ๊ฐ„ ์•ˆ์ „ํ•˜๊ณ  ํšจ์œจ์ ์ธ ๋ฐ์ดํ„ฐ ๊ตํ™˜, ์ผ๋ จ์˜ ๊ทœ์น™์— ๋”ฐ๋ฅธ ์ž๋™ ์ถฉ๋Œ ๊ด€๋ฆฌ ๋“ฑ ๋งŽ์€ ์ž‘์—…์„ ๋…๋ฆฝ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ณ ์œ ํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. SymmetricDS๋Š” ๋”ฐ๋ผ์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ„์˜ ๋ณต์ œ๋Š” ํ”Œ๋žซํผ ๊ฐ„ ๋ฐ์ดํ„ฐ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜, ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜, ๋ฐฐํฌ, ํ•„ํ„ฐ๋ง ๋ฐ ๋ณ€ํ™˜์„ ๋น„๋กฏํ•œ ๋‹ค์–‘ํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค์— ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์ œ๋Š” ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. ๋น ๋ฅธ ๊ฐ€์ด๋“œ SymmetricDS์— ์˜ํ•ด. ์•ˆ์— ์‚ฌ์šฉ์ž ๋งค๋‰ด์–ผ SymmetricDS๋ฅผ ์‚ฌ์šฉํ•œ ๋ณต์ œ ์„ค์ •๊ณผ ๊ด€๋ จ๋œ ๋‹ค์–‘ํ•œ ๊ฐœ๋…์„ ์ž์„ธํžˆ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€