- Published on
MariaDB-FEDERATED엔진으로 DB 동기화 하기
- Authors
- Name
- hongreat
- ✉️hongreat95@gmail.com
MariaDB의 FEDERATED 엔진은 (remote)데이터베이스의 데이터를 복제하거나 클러스터링 없이도 액세스할 수 있게 해주는 스토리지 엔진입니다.
예를 들어서, 로컬 데이터베이스에서 FEDERATED 엔진으로 연결된 remoteDB의 테이블을 연결하면 데이터를 자동으로 가져오고 동기화 됩니다. 이 과정에서 양방향 read/write 또한 가능합니다.
이번 글에서는 docker compose 를 이용해서 로컬단에 구축된 MariaDB에서 FEDERATED 엔진을 사용해 연결하는 과정을 기록합니다.
참고로 MariaDB의 FEDERATED 엔진은 DB 링크와 유사하지만, 정확히는 다릅니다.
DB 링크는 Oracle에서 제공하는 기능으로, 세션을 열고 다양한 작업을 수행할 수 있는 반면, FEDERATED 엔진은 원격 데이터베이스의 테이블과 동기화하는 데 중점을 둡니다. 즉, FEDERATED는 복제나 클러스터링 없이 원격 데이터베이스의 데이터를 로컬에서 접근할 수 있도록 해주는 스토리지 엔진으로, DB 링크보다는 데이터 동기화에 더 가깝습니다.
이번글에 사용될 용어로, 원본은 origin / DB링크를 시도하는 카피본(?) 은 copied 라고 명명하겠습니다.
1. DB 세팅 (on docker)
아래는 Docker Compose
를 사용하여 두 개의 MariaDB 데이터베이스(origin, copied)를 세팅하는 yml 입니다.
각 DB의 port가 충돌 되지 않게 포워딩을 3307/3308 해줘야 합니다.
docker-compose.yml
1. services:
origin-db:
image: mariadb:latest
container_name: origin-db-container
environment:
MYSQL_ROOT_PASSWORD: root_password
MYSQL_DATABASE: origin_db
MYSQL_USER: origin_db_user
MYSQL_PASSWORD: password123
ports:
- "3307:3306"
networks:
- db_network
copied-db:
image: mariadb:latest
container_name: copied-db-container
environment:
MYSQL_ROOT_PASSWORD: root_password
MYSQL_DATABASE: copied_db
MYSQL_USER: copied_db_user
MYSQL_PASSWORD: password123
ports:
- "3308:3306"
networks:
- db_network
networks:
db_network:
driver: bridge
2. Docker Compose 실행
docker compose up -d
3. 각 DB 에 테이블 세팅 및 DB link (Connection)
각 데이터베이스에 접근해 user테이블(db 의 User아님)을 만들어줍니다. 링크가 잘되는지만 확인할 목적이기때문에 최대한 간단한 컬럼으로 구성합니다.
참고(도커로 디비 인스턴스 실행)
docker exec -it origin-db mysql -uorigin_db_user -ppassword123 origin_db
origin-DB
CREATE TABLE user (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(12),
);
copied-DB
링크 시켜줄 DB로 접속하여 테이블을 만들고, FEDERATED 테이블을 만드는 것인데, 아래 DB 링크를 통해서 커넥션을 맺어줍니다.
CREATE TABLE linked_user (
id INT,
name VARCHAR(100)
) ENGINE=FEDERATED CONNECTION='mysql://origin_db_user:password123@origin-db:3306/origin_db/user';
2. FEDERATED 엔진 설치
copied-db
컨테이너에서 MariaDB에 접속한 후 federated 엔진을 설치합니다.
만약 엔진을 활성해주지 않으면 strage engine 에 대한 에러가 발생합니다.(Unknown storage engine 'FEDERATED'
)
INSTALL PLUGIN FEDERATED SONAME 'ha_federated.so';
엔진을 설치할때는 당연히 세팅해둔 MYSQL_ROOT_PASSWORD 를 참고해서 root 계정으로 접속해서 설치합니다. 만약 INSERT command denied to user 'copied_db_user'@'~~~' for table mysql.plugin
처럼 권한에 대한 에러가 발생했다면 root 계정으로 시도 합니다.
엔진 설치 확인
SHOW ENGINES;
명령어로 FEDERATED
엔진이 활성화되었는지 확인합니다.
여기 까지 왔으면 아래처럼 각 DB에 user / linked_user 테이블이 잘 생성되었는지 확인합니다.
3. 연결확인
데이터 삽입
기대한 결과는 origin db에 데이터를 넣었을때, copied db 에서 확인(및 조회) 가 되는 것 입니다.
- origin-DB에 데이터 삽입
origin DB에 접속하여 employees
테이블에 테스트 데이터를 추가합니다
# origin_db 에서 실행
INSERT into user (name) VALUES ('브루노마스');
- copied-DB에서 데이터 확인
# copied_db 에서 실행
SELECT * FROM linked_user;
이제 copied DB에서 잘 보여지는지 확인하고 잘 보여진다면 완료 입니다.
4. Copied DB를 읽기 전용으로 세팅
위의 과정을 잘 수행했다면, origin-copied DB간 양방향 통신이 가능해야 합니다.
그 말은 곧 origin-DB에 데이터 삽입 시, copied-DB에도 보여져야 한다는 것 입니다.
‘물리적인 복제’ 와 ‘단방향 읽기권한’ 등이 요구사항이라면 DB-Link라는 방법이 적절하지 못한 방법이 됩니다.
여기서 부터는 읽기만 되도록하는 방법이 필요해서 세팅한 과정입니다.
참고로, 저의 경우 copied-DB 를 사용하는 곳이 WAS(Django)였고, 이런 경우에는 DB using
하는 부분에서 write 에 대한 로직을 손봐도 읽기만 세팅 되긴 합니다.
하지만 혹시 모를 상황을 생각한다면 WAS뿐이 아닌, copied-DB 에서도 읽기만 되는 것이 보다 안전하다고 생각합니다. ( 이중으로 안전장치를 마련해 두는 것이죠.)
origin-DB User 생성과 권한 부여
DB에 접속한 후, 읽기 전용 사용자 계정을 추가합니다.
CREATE USER 'read_only_user'@'%' IDENTIFIED BY 'read_only_password';
GRANT SELECT ON adb.* TO 'read_only_user'@'%';
FLUSH PRIVILEGES를 통해 권한을 반영합니다.
FLUSH PRIVILEGES;
read_only_user
라는 사용자 계정을 만들고, 해당 origin-DB 의 User 에 대해 SELECT
권한만 부여합니다.
FLUSH PRIVILEGES;
는 MySQL(MariaDB)에서 권한 테이블의 변경 사항을 적용하는 명령어입니다.
읽기전용의 Link Table 추가
CREATE TABLE linked_user_but_read_only (
id INT,
name VARCHAR(100)
) ENGINE=FEDERATED CONNECTION='mysql://read_only_user:read_only_password@origin-db:3306/origin_db/user';
그리고 아래 처럼 링크되었지만, 연결조건에 read_only 제한을 걸어둔 테이블에 INSERT를 시도하게 되면 아래 에러가 발생합니다.(values에 박해일은 박해일 배우님으로, 인서트한 이유는 별거아닙니다..)
copied_db> INSERT into linked_user_but_read_only (name) VALUES ('박해일')
Got error 10000 'Error on remote system: 1142: INSERT command denied to user 'read_only_user'@'!@#$!@' for table origin_db.user' from FEDERATED
5. 결론
이렇게 FEDERATED 으로 연결된 DB는 다음과 같은 특징이 있습니다.
- origin-db & copied-db는 네트워크를 통해서 가상으로 동기화 되는 상태입니다.
- origin-db 가 종료되면, copied-db에서 조회도 안됨
- Unknown server host 'copied-db'
- copied-db (의 origin-db와 connection 된) table 에서 데이터를 INSERT 하는 경우 orgin-db에도 생성됩니다.
- 연결에 필요한건 엔진과 DB접속 정보이며, 유저권한에 대한 것도 그대로 동작합니다.
이러한 특징으로 인해, 개발 요구사항이 ‘가상테이블 개념의 실시간 동기화가 필요한 경우’ 이거나, ‘양방향 read/write’ 가 되어야하는 경우라면 DB Link 가 하나의 좋은 방법이 될 수 있습니다.
이번 글에서 사용된 코드 일부를 깃허브에 퍼블릭으로 업로드했으니, 필요하신분들은 참고하시길 바랍니다.