3.Altibase Sharding 사용방법#
이 장에서는 Altibase Sharding 사용 방법을 자세히 설명한다. 앞에서 설명한 샤드 노드 설정과 샤드 패키지 생성 과정 이후의 사용 방법을 기술한다.
Altibase Sharding 제약사항#
Altibase Sharding은 아래와 같은 제약 조건을 갖는다.
선행 조건#
- 샤딩은 하나의 데이터베이스를 여러 데이터베이스로 나누어 저장하는 기술이다. 따라서 각 데이터베이스는 서로 독립적으로 운영되고 관리되어야 한다.
- 샤드 메타 설정은 반드시 DBMS_SHARD 패키지를 사용해야 한다.
- 전체 샤딩 시스템에서 동작하는 샤드 노드들은 샤드 메타 및 샤드 관련 테이블 스키마 정보가 동일해야 한다.
- 날짜 함수등의 결과가 일부 달라져서 에러가 발생할 수 있으므로 모든 노드의 프로퍼티나 서버 설정등의 구성(DB 구성포함)은 동일해야한다.
- ALTERNATE 노드는 하나만 설정 가능하다. 2개 이상의 ALTERNATE 노드를 지원하지 않는다.
데이터 제약조건#
- 샤드 키는 UPDATE 구문을 수행할수 없다.
- 샤드 키를 UPDATE하려면 DELETE 이후에 INSERT 를 수행해야 한다.
- 샤드 키 분산 테이블에서 기본 키 또는 유니크 속성을 갖는 컬럼은 샤드 키와 동일한 컬럼이어야 한다. 그렇지 않은 경우 샤딩 시스템 전역에서 유니크 속성에 대한 정합성을 보장하지 않는다.
- 단일 샤드 키 테이블의 생성시 해당 샤드 테이블 분산 방식에 대응되는 파티션드 테이블로 생성해야 하며 파티션 키와 샤드 키는 동일해야한다.
- 각 파티션의 경계는 분산 경계를 포함해야 한다.
- 응용 프로그램은 AUTOCOMMIT OFF로 수행해야만 한다.
- 응용 프로그램에서 DCL(COMMIT/ROLLBACK,SAVEPOINT), DDL에 대해서 DIRECT EXECUTE(직접) 수행 시 정합성 깨질수 있다.
- 다수의 응용프로그램이 하나의 트랜잭션으로 다수의 노드에 접근하는 경우 순간적으로 다른 응용 프로그램이 COMMIT을 수행한 데이터중 일부만 보일수 있다.
- 샤드 프로시져 내부에서 동작하는 구문은 분산처리 되지 않고, 해당 노드에 로컬로 동작한다.
- 다수의 응용프로그램에서 CLONE TABLE 에 대하여 갱신 수행시 노드간 데이터 정합성이 깨질수 있다.
- 단일 응용프로그램에서 갱신을 수행하면 정합성이 깨지지 않는다.
데드락#
- 다수의 응용프로그램이 한 트랜잭션에서 여러 테이블에 접근시 데드락이 발생할 수 있다.
- 다수의 응용프로그램에서 CLONE TABLE에 대해 갱신 수행시 데드락이 발생할 수 있다.
샤드 노드 장애#
- 여러 개의 샤드 노드들 중에서 일부 샤드 노드에 네트워크나 서버 장애가 발생하는 경우가 있다.
이것을 전체 데이터베이스 시스템의 장애로 볼 것인지, 일부 데이터베이스 시스템의 장애로 볼 것인지는 응용프로그램마다 다를 수 있다.
- 하나의 쿼리가 장애 노드와 비 장애 노드에 모두 접근하는 경우에는 해당 쿼리수행은 에러처리가 된다.
- 장애 노드에 접근하지 않는 작업은 정상 동작한다.
- 응용프로그램에서 커넥션을 생성할 때, 일부 샤드 노드에 대한 커넥션이 장애가 발생하면 이를 에러로 처리하고 커넥션 생성이 실패한다. 단, jdbc는 응용프로그램에서 커넥션을 생성할 때 사용자 커넥션의 접속까지만 이루어지기 때문에 노드 장애여부와 상관없이 사용자 커넥션만 정상적이라면 커넥션이 생성된다.
- 커넥션 생성 후 쿼리 수행시 일부 샤드 노드에 장애가 발생하더라도 장애가 발생하지 않는 샤드 노드는 서비스를 계속 수행할 수 있다.
- 일부 샤드 노드의 장애에도 불구하고 나머지 샤드 노드에서 서비스를 계속하기 위해서는 응용프로그램의 에러 처리 방식을 수정하는 것을 통해서 서비스를 지속할 수 있다.
- 특정 노드의 장애 복구후 응용프로그램중 일부는 ALTERNATE 노드에 접속되어 있고 일부는 PRIMARY 노드에 접속되어 있을 수 있다.
- 다수의 노드를 갱신한 트랜잭션이 COMMIT 중에 노드 장애가 발생하면 해당 노드에서 갱신된 데이터는 복구가 불가능하다.
- CLONE 객체에 대한 장애복구는 사용자가 직접 수행해야 한다.
하위 호환성#
- 샤드 기능은 하위 호환성을 갖지 않는다. 샤드 버전이 동일한 서버, 클라이언트에 대해서만 샤드 기능을 사용할 수 있다.
지원하지 않는 기능#
아래 나열된 기능들은 분산 객체로 지원하지 않거나 분산처리 되지 않는다.
- SSL
- TRIGGER, VIEW, UPDATABLE VIEW, QUEUE
- JOB SCHEDULER
- GLOBAL SEQUENCE
- PACKAGE, 일부 집계 함수를 제외한 모든 FUNCTION
-
다중 반환값(PROCEDURE OUT PARAMETER)
- 여러 노드의 반환값을 모든 어플리케이션에서 알아야 하는 경우에는 Clone Procedure 내에서 해당 정보들을 테이블에 입력한 이후에 별도의 조회 쿼리를 수행하여 알수 있다.
-
샤드 프로시져에 KEY 타입
-
IN OUT, OUT
- 샤드에서 지원하지 않는 데이터 타입 유형
- FOREIGN KEY, PRIMARY KEY, UNIQUE KEY(UNIQUE INDEX)
- LOB/GEOMETRY
- 보안컬럼
- MOVE, MERGE
- FETCH ACROSS COMMIT/ROLLBACK
- SAVEPOINT
- FAILOVER CALLBACK
동시 사용 불가#
아래 나열된 기능들은 샤딩과 동시에 사용할수 없다.
- DBLINK
- XA
리샤딩#
- COMPOSITE SHARD KEY를 사용시 리샤딩이 지원되지 않는다.
- NODE/SHARD등의 PREFIX를 사용시 리샤딩이 지원되지 않는다.
- 한번에 하나의 PARTITION만 리샤딩이 가능하다.
- 테이블에 PRIMARY KEY가 존재해야 리샤딩이 가능하다.
튜닝 요건#
- 데이터가 분산 가능한 형태인 경우에 효과적이다. 사용자의 업무 형태, 데이터 특성에 따라 샤딩의 적용 여부를 판단해야 한다.
- 데이터가 분산 가능하지 않거나 대부분의 질의가 샤드 쿼리가 아닌 경우, 샤딩을 적용하더라도 여러 데이터베이스를 다루는 부하때문에 하나의 데이터베이스로 운영하는 것에 비해 장점이 많지 않다.
- 여러 샤드 노드에 데이터의 로드가 고르게 분산되어야 한다. 이를 위하여 분산 방식과 샤드 키를 적절하게 선택해야 한다.
- 운영 중에 데이터가 고르게 분산되어 있는지 확인하고 필요한 경우에는 데이터를 재분산 해야 한다.
Altibase Sharding 통신 방법#
샤딩에서 사용하는 커넥션에 따라 지원하는 통신 방법은 다음과 같다.
사용자 커넥션(User Connection)#
사용자 커넥션 스트링의 CONN_TYPE 속성에 해당하며 Altibase 에서 제공하는 통신방법과 동일하다. 자세한 내용은 Administrator manual의 서버/클라이언트 통신 장을 참고한다.
샤드 라이브러리 커넥션(Shard Library Connection)#
샤드 라이브러리 커넥션의 통신 방법으로 사용자 커넥션 스트링의 SHARD_CONNTYPE 속성에 해당하며 다음의 통신 타입을 지원한다. SHARD_CONNTYPE 을 명시하지 않을 경우 TCP 를 기본값으로 동작한다.
- 1: TCP (기본값)
- 8: IB (InfiniBand)
코디네이터 커넥션(Coordinator Connection)#
코디네이터와 샤드 노드의 내부 커넥션 통신 방법으로 노드 설정시 지정 가능하며 다음의 통신 타입을 지원한다. 노드 설정의 인자로 명시하지 않을 경우 TCP 를 기본값으로 동작한다.
- 1: TCP (기본값)
- 8: IB (InfiniBand)
샤드 노드#
Altibase Sharding을 사용하기 위하여 각 샤드 노드에 샤딩 관련 정보를 설정해야 한다.
샤딩 관련 메타 정보는 샤드 메타 식별자(META_NODE_ID) 를 제외하고는 모두 동일하게 유지해야 한다.
샤딩 시스템을 최초로 구성하거나 노드를 추가하기 위해서는 모든 노드에 동일한 순서로 샤드 노드 설정 과정을 거치거나 aexport 등을 이용해 복제하여, 샤드 메타 정보를 동일하도록 유지해야 한다.
샤드 노드 설정을 전역적으로 적용하기 위해서 샤드 매니저를 사용하는 것을 권장한다.
수동으로 설정 하는 경우 가용 노드를 포함한 모든 샤드 노드에서 동일한 설정 작업을 수행하고 작업의 완료를 알리기 위해서 샤드 메타 적용 구문(ALTER SYSTEM RELOAD SHARD META NUMBER LOCAL)을 수행해야 한다.
AUTOCOMMIT OFF;
EXEC DBMS_SHARD.SET_NODE(‘node1’,‘192.168.1.10’,20300);
EXEC DBMS_SHARD.SET_NODE(‘node2’,‘192.168.1.11’,20300,‘192.168.1.101’,20300);
COMMIT;
ALTER SYSTEM RELOAD SHARD META NUMBER LOCAL;
샤드 노드 추가#
샤드 패키지인 DBMS_SHARD 패키지에는 샤드 노드를 추가하는 서브 프로그램을 제공한다. 샤드 노드를 추가하기 위해서는 샤드 패키지를 생성해야 한다.
구문#
DBMS_SHARD.SET_NODE
설명#
샤드 노드를 추가한다. 필요에 따라 alternate 샤드 노드를 추가할 수 있다. 샤드 노드 이름의 대소문자는 구별하지 않는다.
현재 ip address는 ip v4형식만 지원한다.
예제#
EXEC DBMS_SHARD.SET_NODE(‘node1’,‘192.168.1.10’,20300);
EXEC DBMS_SHARD.SET_NODE(‘node2’,‘192.168.1.11’,20300, ‘192.168.1.101’,20300);
SELECT * FROM sys_shard.nodes_;
샤드 노드 삭제#
샤드 패키지인 DBMS_SHARD 패키지에는 샤드 노드를 삭제하는 서브 프로그램을 제공한다.
구문#
DBMS_SHARD.UNSET_NODE
설명#
추가한 샤드 노드를 삭제한다.
예제#
EXEC DBMS_SHARD.UNSET_NODE(‘node1’);
SELECT * FROM sys_shard.nodes_;
샤드 객체#
Altibase Sharding은 현재 다음 두 가지 샤드 객체(shard object)를 지원한다. 샤드 객체란 일반 테이블 혹은 프로시저에 샤드 설정을 추가한 객체를 의미한다.
-
샤드 테이블
-
샤드 프로시저
샤드 객체에 샤드를 설정하기 위해서는 아래의 절차를 수행하여야 한다.
- 테이블에 샤드 키 컬럼 지정 또는 프로시저에 샤드 키 파라미터 지정
- 분산 방식 지정
- 분산 노드 지정
샤드 객체 설정을 전역적으로 적용하기 위해서 샤드 매니저를 사용하는 것을 권장한다.
수동으로 설정 하는 경우 가용 노드를 포함한 모든 샤드 노드에서 동일한 설정 작업을 수행하고 작업의 완료를 알리기 위해서 샤드 메타 적용 구문(ALTER SYSTEM RELOAD SHARD META NUMBER LOCAL)을 수행해야 한다.
AUTOCOMMIT OFF;
EXEC DBMS_SHARD.SET_SHARD_TABLE(‘user1’,‘t1’,‘h’,‘i1’,‘node1’);
EXEC DBMS_SHARD.SET_SHARD_TABLE(‘user1’,‘t2’,‘r’,‘i1’,‘node1’);
COMMIT;
ALTER SYSTEM RELOAD SHARD META NUMBER LOCAL;
주의 사항
- 샤드 객체 설정은 데이터의 이동을 수반하지 않는다. 데이터 이동 관련 내용은 "리샤딩"을 참고한다.
샤드 테이블 생성#
샤드 테이블을 설정하기 위해서 먼저 각 샤드 노드에 테이블이 생성되어 있어야 한다.
샤드 테이블은 단일 샤드 키 분산 테이블과 복합 샤드 키 분산 테이블, 복제 분산 테이블 그리고 독립 분산 테이블이 있다.
복제 분산 테이블과 독립 분산 테이블 그리고 복합 샤드 키 분산 테이블은 Altibase의 일반 테이블 생성과 동일하며, 모든 샤드 노드에 동일한 스키마의 테이블을 생성한다. 단일 샤드 키 분산 테이블은 샤드 키 컬럼을 파티션 키로 하여 파티션드 테이블로 생성해야한다.
단일 샤드 키 분산 테이블은 분산 방식에 따라 각 샤드 테이블 유형에 대응되는 파티션드 테이블을 생성해야 한다.
| 샤드 테이블 | 파티셔닝 방법 |
|---|---|
| 해시 분산 테이블 | RANGE_USING_HASH |
| 범위 분산 테이블 | RANGE |
| 리스트 분산 테이블 | LIST |
[표 2]. 단일 샤드 키 분산 테이블 별 파티셔닝 방법
[표 2]에 나타난 것과 같이 해시 분산 테이블의 경우 RANGE_USING_HASH, 범위 분산 테이블의 경우 RANGE 그리고 리스트 분산 테이블의 경우 LIST 파티션드 테이블로 생성해야 하며, 파티션 키와 샤드 키는 동일한 컬럼을 사용해야 한다.
테이블 생성시 파티션의 범위는 분산 범위와 동일하거나 노드 확장을 위해서 더 세부적으로 지정하는 것을 추천한다.
만약 샤드 노드 2개를 사용하며 해시로 분산하며 향후 샤드 노드 2개를 더 추가할 계획을 가지고 있다면 4개의 파티션을 생성하는 것이 노드 추가 및 데이터 이동 시 유리하다.
구문#
CREATE TABLE
설명#
샤드 테이블을 생성한다. CREATE TABLE에 대한 자세한 내용은 SQL Reference를 참고한다.
예제#
CREATE TABLE T1(I1 INTEGER PRIMARY KEY, I2 CHAR(10))
PARTITION BY RANGE_USING_HASH ( I1 )
(
PARTITION P1 VALUES LESS THAN (250),
PARTITION P2 VALUES LESS THAN (500),
PARTITION P3 VALUES LESS THAN (750),
PARTITION P4 VALUES DEFAULT
);
Create success.
CREATE TABLE T2(I1 CHAR(10) PRIMARY KEY, I2 CHAR(100));
Create success.
샤드 테이블 설정#
테이블을 샤드 테이블로 설정한다. 샤드 노드에 미리 생성되어 있는 테이블에 샤드 설정을 추가한다.
샤드 설정 후, 샤드 쿼리를 수행하기 위하여 모든 샤드 노드에 동일한 스키마의 테이블이 생성되어 있어야 한다. DBMS_SHARD 패키지는 샤드 테이블을 추가하는 서브 프로그램을 제공한다.
구문#
DBMS_SHARD.SET_SHARD_TABLE
DBMS_SHARD.SET_SHARD_TABLE_COMPOSITE
설명#
샤드 테이블을 설정한다. 샤드 테이블 설정 구문에 대한 자세한 설명은 DBMS_SHARD 패키지의 SET_SHARD_TABLE 또는 SET_SHARD_TABLE_COMPOSITE를 참조한다.
예제#
EXEC DBMS_SHARD.SET_SHARD_TABLE(‘user1’,‘t1’,‘h’,‘i1’,‘node1’);
EXEC DBMS_SHARD.SET_SHARD_TABLE_COMPOSITE(‘user1’,‘t2’,‘h’,‘i1’,‘r',‘i2',‘node1’);
SELECT * FROM sys_shard.objects_;
샤드 테이블 해제#
샤드 테이블을 해제할 수 있다. 샤드 테이블을 해제한다고 해서 테이블까지 삭제되는 것은 아니며, 테이블을 삭제하더라도 샤드 테이블이 해제되지는 않는다. 샤드 테이블의 설정은 테이블의 이름에 기반하므로 테이블이 재생성되고 샤드 키 이름이 동일하게 생성된다면 이전에 생성한 샤드 설정은 유효하다.
DBMS_SHARD 패키지에는 샤드 테이블을 해제하는 서브 프로그램을 제공한다.
구문#
DBMS_SHARD.UNSET_SHARD_TABLE
설명#
샤드 테이블을 해제한다.
예제#
EXEC DBMS_SHARD.UNSET_SHARD_TABLE(‘user1’,‘t1’);
샤드 프로시저 설정#
샤드 프로시저는 일반 프로시저에 샤드 설정을 추가한 프로시저를 말한다.
샤드 프로시저는 실제 데이터를 갖지 않지만, 데이터를 다루는데 사용하는 함수로서 프로시저가 분산된 데이터를 처리한다. 프로시저의 수행을 분산하여 샤딩에서 사용할 수 있다.
샤드 프로시저의 파라미터들 중 하나가 샤드 키로 사용되며, 프로시저가 호출될 때의 파라미터 값으로 샤드 노드를 선택하여 선택된 노드에서 프로시저가 수행된다.
DBMS_SHARD 패키지는 샤드 프로시저를 추가하는 서브 프로그램을 제공한다.
구문#
DBMS_SHARD.SET_SHARD_PROCEDURE
DBMS_SHARD.SET_SHARD_PROCEDURE_COMPOSITE
설명#
샤드 프로시저를 설정한다. 샤드 프로시저 설정 구문에 대한 자세한 설명은 DBMS_SHARD 패키지의 SET_SHARD_PROCEDURE 또는 SET_SHARD_PROCEDURE_COMPOSITE을 참조한다.
예제#
EXEC DBMS_SHARD.SET_SHARD_PROCEDURE(‘user1’,‘proc1’,‘h’,‘p1’,‘node1’);
EXEC DBMS_SHARD.SET_SHARD_PROCEDURE_COMPOSITE(‘user1’,‘proc2’,‘h’,‘p1’,‘l',‘p2',‘node1’);
SELECT * FROM sys_shard.objects_;
샤드 프로시저 해제#
샤드 프로시저를 해제할 수 있다. 샤드 프로시저를 해제하여도 프로시저까지 삭제되는 것은 아니다. 또한, 프로시저를 삭제하더라도 샤드 프로시저가 해제되는 것은 아니다. 샤드 프로시저의 설정은 프로시저의 이름에 기반하므로 프로시저가 재생성되고 샤드 키 파라미터의 이름이 동일하게 생성된다면 이전에 생성한 샤드 설정은 유효하다.
DBMS_SHARD 패키지에는 샤드 프로시저를 해제하는 서브 프로그램을 제공한다.
구문#
DBMS_SHARD.UNSET_SHARD_PROCEDURE
설명#
샤드 프로시져를 해제한다.
예제#
EXEC DBMS_SHARD.UNSET_SHARD_PROCEDURE (‘user1’,‘proc1’);
분산 정보 설정#
Altibase Sharding은 샤드 객체에 대하여 다음과 같은 분산 방식(split method)으로 분산 정보를 설정한다.
-
단일 샤드 키 분산 설정
-
해시(hash) 분산 설정
-
범위(range) 분산 설정
-
리스트(list) 분산 설정
-
-
복합(composite) 샤드 키 분산 설정
-
복제(clone) 분산 설정
-
독립(solo) 분산 설정
본 장에서는 각 분산 방식에 대해 수동으로 설정하는 방법을 설명한다.
분산 정보 설정을 전역적으로 적용하기 위해서 샤드 매니저를 사용하는 것을 권장한다.
수동으로 설정 하는 경우 가용 노드를 포함한 모든 샤드 노드에서 동일한 설정 작업을 수행하고 작업의 완료를 알리기 위해서 샤드 메타 적용 구문(ALTER SYSTEM RELOAD SHARD META NUMBER LOCAL)을 수행해야 한다.
AUTOCOMMIT OFF;
EXEC DBMS_SHARD.SET_SHARD_HASH(‘user1’,‘t1’,300,‘node1’);
EXEC DBMS_SHARD.SET_SHARD_HASH(‘user1’,’‘t1’,600,‘node2’);
EXEC DBMS_SHARD.SET_SHARD_HASH(‘user1’,’‘t1’,1000,‘node3’);
COMMIT;
ALTER SYSTEM RELOAD SHARD META NUMBER LOCAL;
주의 사항
- 분산 설정은 데이터의 이동을 수반하지 않는다. 데이터 이동 관련 내용은 "리샤딩"을 참고한다.
해시(Hash) 분산 설정#
해시 분산은 샤드 키 값을 hash하여 분산하는 방식이다.
Altibase Sharding은 hash 값을 0부터 999까지 1000개의 hash group으로 관리한다.
Hash group 0부터 299까지는 node1에 저장하고, hash group 300부터 599까지는 node2에 저장하고, hash group 600부터 999까지는 node3에 저장할 경우 다음과 같이 분산 정의한다.
- hash_group[\<300] -> node1
- hash_group[\<600] -> node2
- hash_group[\<1000] -> node3
만일 기본 샤드 노드가 node3으로 정의되어 있다면 마지막 정의는 생략해도 동일하다.
구문#
DBMS_SHARD.SET_SHARD_HASH
설명#
해시 방식의 분산 정보를 설정한다.
예제#
user1 사용자의 t1은 이미 해시 분산으로 설정되어 있다고 가정한다.
EXEC DBMS_SHARD.SET_SHARD_HASH(‘user1’,‘t1’,300,‘node1’);
EXEC DBMS_SHARD.SET_SHARD_HASH(‘user1’,’‘t1’,600,‘node2’);
EXEC DBMS_SHARD.SET_SHARD_HASH(‘user1’,’‘t1’,1000,‘node3’);
SELECT * FROM sys_shard.ranges_;
범위(Range) 분산 설정#
범위 분산은 샤드 키 값의 범위를 지정하여 분산하는 방식이다.
샤드 키 값이 ‘H’ 보다 작은 경우 node1에 저장하고, ‘H’보다 크고 ‘T’보다 작은 경우 node2에 저장하고, ‘T’보다 크고 ‘Z’보다 작은 경우 node3에 저장한다.
- shard key value \< ‘H’ 경우 –> node1
- ‘H’ \<= shard key value \< ‘T’ 경우’ –> node2
- ‘M’ \<= shard key value \< ‘Z’ 경우 –> node3
샤드 키 값이 NULL인 경우 만약 기본 샤드 노드가 정의되지 않았다면 에러가 발생하게 된다.
구문#
DBMS_SHARD.SET_SHARD_RANGE
설명#
범위 방식의 분산 정보를 설정한다.
예제#
user1 사용자의 t1은 이미 범위 분산으로 설정되어 있다고 가정한다.
EXEC DBMS_SHARD.SET_SHARD_RANGE(‘user1’,‘t1’,‘H’,‘node1’);
EXEC DBMS_SHARD.SET_SHARD_RANGE(‘user1’,‘t1’,‘T’,‘node2’);
EXEC DBMS_SHARD.SET_SHARD_RANGE(‘user1’,‘t1’,‘Z’,’‘node3’);
SELECT * FROM sys_shard.ranges_;
리스트(List) 분산 설정#
리스트 분산은 샤드 키 값을 equal 연산으로 비교하여 분산하는 방식이다.
샤드 키 값이 ‘서울’인 경우 node1에 저장하고, ‘부산’인 경우 node2에 저장하고, ‘대구’인 경우 node3에 저장한다.
-
‘서울’ –> node1
-
‘부산’ –> node2
-
‘대구’ –> node3
이 때 ‘서울’, ‘부산’, ‘대구’ 외의 샤드 키 값은 기본 샤드 노드에 저장된다. 만약 기본 샤드 노드가 정의되지 않았다면 에러가 발생한다.
구문#
DBMS_SHARD.SET_SHARD_LIST
설명#
리스트 방식의 분산정보를 설정한다.
예제#
user1 사용자의 t1은 이미 list 분산으로 설정되어 있다고 가정한다.
EXEC DBMS_SHARD.SET_SHARD_LIST(‘user1’,‘t1’,‘서울’, ‘node1’);
EXEC DBMS_SHARD.SET_SHARD_LIST(‘user1’,‘t1’,‘부산’, ‘node2’);
EXEC DBMS_SHARD.SET_SHARD_LIST(‘user1’,‘t1’,‘대구’, ‘node3’);
SELECT * FROM sys_shard.ranges_;
복합(Composite) 샤드 키 분산 설정#
Altibase Sharding 은 두 개의 샤드 키를 적용하는 분산 방법으로 복합 샤드 키 분산을 제공한다.
샤드 키 분산 방식(hash, range, list)중에서 두 개의 샤드 키를 적용한 다중 분산 기법으로써, 각각의 샤드 키는 서로 다른 분산 방법을 적용할 수 있다. 단, 복합 샤드 키를 적용할 경우에는 아래의 패키지를 적용하여 샤드 객체를 설정해야 한다.
-
SET_SHARD_TABLE_COMPOSITE
-
SET_SHARD_PROCEDURE_COMPOSITE
복합 샤드 키를 적용한 샤드 객체를 해제 방법은 샤드 객체 해제 방법과 동일하다.
구문#
DBMS_SHARD.SET_SHARD_COMPOSITE
설명#
복합 샤드 키 분산 정보를 설정한다.
예제#
user1 사용자의 t1은 이미 복합 샤드 키 분산으로 설정되어 있다고 가정한다.
EXEC DBMS_SHARD.SET_SHARD_COMPOSITE(‘user1’,‘t1’,‘서울’,‘강남구’,‘node1’);
EXEC DBMS_SHARD.SET_SHARD_COMPOSITE(‘user1’,‘t1’,‘서울’,‘강북구’,‘node2’);
EXEC DBMS_SHARD.SET_SHARD_COMPOSITE(‘user1’,‘t1’,‘서울’,‘강서구’,‘node3’);
EXEC DBMS_SHARD.SET_SHARD_COMPOSITE(‘user1’,‘t1’,‘부산’,‘강서구’,‘node1’);
EXEC DBMS_SHARD.SET_SHARD_COMPOSITE(‘user1’,‘t1’,‘부산’,‘금정구’,‘node2’);
EXEC DBMS_SHARD.SET_SHARD_COMPOSITE(‘user1’,‘t1’,‘부산’,‘남구’,‘node3’);
SELECT * FROM sys_shard.ranges_;
복제(Clone) 분산 설정#
복제 분산은 샤드 키를 적용한 데이터 분산이 아닌 샤드 객체가 복제되어 저장된 상태를 의미한다. 복제 분산을 적용하는 샤드 객체는 샤드 키가 필요없고 복제될 샤드 노드만 지정한다.
구문#
DBMS_SHARD.SET_SHARD_CLONE
설명#
복제 방식의 분산정보를 설정한다.
예제#
user1 사용자의 t1은 이미 복제 분산으로 설정되어 있다고 가정한다.
EXEC DBMS_SHARD.SET_SHARD_CLONE(‘user1’,‘t1’,‘node1’);
EXEC DBMS_SHARD.SET_SHARD_CLONE(‘user1’,‘t1’,‘node2’);
EXEC DBMS_SHARD.SET_SHARD_CLONE(‘user1’,‘t1’,‘node3’);
SELECT * FROM sys_shard.clones_;
주의 사항
- 복제 분산 테이블로 설정 이후에 들어온 DML에 대해서 복제된다.
- 장애가 발생한 노드의 데이터의 동기화는 자동으로 이뤄지지 않으므로 장애 복구후 데이터 동기화는 수동으로 수행해야한다.
독립(Solo) 분산 설정#
독립 분산은 샤드 키를 적용한 데이터 분산이 아닌 샤드 객체 단위의 분산 방식이다. 독립 분산 역시 샤드 키를 지정하지 않고 사용자가 원하는 하나의 노드를 지정한다.
구문#
DBMS_SHARD.SET_SHARD_SOLO
설명#
독립 방식의 분산정보를 설정한다.
예제#
user1 사용자의 t1은 이미 독립 분산으로 설정되어 있다고 가정한다.
EXEC DBMS_SHARD.SET_SHARD_SOLO(‘user1’,‘t1’,‘node1’);
SELECT * FROM sys_shard.solos_;
샤드 키#
샤드 키(shard key)는 데이터를 분산하는 기준이 되는 테이블의 컬럼 혹은 프로시저의 파라미터를 말한다. 샤드 키는 최대 두 개의 컬럼 혹은 파라미터에 대해서 정의할 수 있다.
샤드 키는 다음과 같은 데이터 타입을 지원한다.
-
smallint
-
integer
-
bigint
-
char
-
varchar
샤드 키의 설정에 대한 설명은 이 장의 '샤드 객체'를 참고한다.
샤드 트랜잭션#
Altibase Sharding은 분산된 여러 데이터베이스를 다루게 되므로 이에 대한 트랜잭션 처리가 필요하다. Altibase Sharding에서 다루는 여러 데이터베이스에 대한 트랜잭션을 다음과 같이 구분한다.
- 다중 노드 트랜잭션 (multiple node transaction)
다중 노드 트랜잭션#
Altibase Sharding에서 ACID는 보장하지는 않지만, 여러 샤드 노드에 대한 트랜잭션을 허용하는 트랜잭션을 말한다.
Altibase Sharding에서 트랜잭션을 시작할 때 다중 노드 트랜잭션을 선언하면 여러 샤드 노드에 모두 쿼리를 수행할 수 있다. 트랜잭션의 커밋, 롤백은 모든 샤드 노드로 순차적으로 수행된다.
커밋 또는 롤백 시 샤드 노드에 장애가 발생한 경우, 샤드 라이브러리는 그 즉시 에러를 반환한다. 따라서, 데이터의 일관성 확인이 필요하다.
구문#
SQLSetConnectAttr (
SQLHDBC dbc,
SQLINTEGER Attribute,
SQLPOINTER ValuePtr,
SQLINTEGER StringLength );
설명#
다중 노드 트랜잭션을 설정한다. 다중 노드 트랜잭션으로 설정할 때에는
Attribute에는 ALTIBASE_GLOBAL_TRANSACTION_LEVEL으로 ValuePtr에는 ALTIBASE_MULTIPLE_NODE_TRANSACTION을 입력한다.
SQLSetConnectAttr에 대한 자세한 설명은 “CLI User's Manual > 2. Altibase CLI
함수”를 참조한다.
jdbc같은 경우 CLI의 SQLSetConnectAttr이 없기 때문에 연결속성의 형태로 지원한다.
예제#
ShardCLI#
SQLSetConnectAttr(dbc, ALTIBASE_GLOBAL_TRANSACTION_LEVEL, (void*)ALTIBASE_MULTIPLE_NODE_TRANSACTION, 0);
ShardJDBC#
DriverManager.getConnection("jdbc:sharding:Altibase://ip_address:port/mydb?shard_transaction_level=1");
글로벌 트랜잭션#
Altibase Sharding에서 ACID를 보장하면서 여러 샤드 노드에 대한 트랜잭션 일관성을 보장하는 트랜잭션을 말한다.
구문#
SQLSetConnectAttr (
SQLHDBC dbc,
SQLINTEGER Attribute,
SQLPOINTER ValuePtr,
SQLINTEGER StringLength );
설명#
글로벌 트랜잭션을 설정한다. 글로벌 트랜잭션으로 설정할 때에는 Attribute에는 ALTIBASE_GLOBAL_TRANSACTION_LEVEL으로 ValuePtr에는 ALTIBASE_GLOBAL_TRANSACTION을 입력한다. SQLSetConnectAttr에 대한 자세한 설명은 “CLI User's Manual > 2. Altibase CLI 함수”를 참조한다.
예제#
ShardCLI#
SQLSetConnectAttr(dbc, ALTIBASE_GLOBAL_TRANSACTION_LEVEL, (void*)ALTIBASE_GLOBAL_TRANSACTION, 0);
ShardJDBC#
DriverManager.getConnection("jdbc:sharding:Altibase://ip_address:port/mydb?shard_transaction_level=2");
샤드 쿼리#
샤드 쿼리(shard query)란 분산된 각 데이터베이스에서의 질의 결과의 합이 논리적으로 분산되지 않은 상태의 데이터베이스 질의 결과와 같은 경우를 말한다.
Altibase Sharding은 다음과 같은 구문을 지원한다.
-
INSERT
-
INSERT SELECT
-
UPDATE
-
DELETE
-
SELECT
각 구문에 대해 대표적인 샤드 쿼리의 판단 기준은 다음과 같다.
-
샤드 키에 대한 equal value 형식의 조건절이 있는 형태
-
SELECT * FROM t1과 같이 단순히 결과를 취합하는 형태
그러나 현실에서는 보다 다양하고 복잡한 형태의 쿼리가 수행되므로 일부 사례 설명을 위해 아래와 같은 테이블이 생성되어 있다고 가정한다.
-
동일한 샤드 키 분산 방식을 적용한 샤드 테이블 s1, s2
-
(샤드 키 컬럼 k1, 일반 컬럼 i1)
-
복제 분산 방식을 적용한 샤드 테이블 c1 (일반 컬럼 i1)
-
독립 분산 방식을 적용한 샤드 테이블 so1 (일반 컬럼 i1)
-
일반 테이블 t1 (일반 컬럼 i1)
INSERT#
모든 샤드 테이블(s1, c1, so1)에 대해 모든 형태의 insert 구문을 지원한다.
Insert 값에 따라 단일 샤드 노드에서 수행하는 샤드 쿼리는 다음과 같다.
-
INSERT INTO s1(k1, i1) VALUES(?, 2);
-
INSERT INTO so1(i1) VALUES(?);
샤드 키 분산 테이블에 INSERT를 수행하는 경우 샤드 키에 해당하는 값에 수식이 있거나, 시퀀스, 또는 서브 쿼리가 있을 수 있다. 이 때 샤드 코디네이터가 그 값을 미리 계산한 후에 해당 노드로 전달한다.
-
INSERT INTO s1(i1, i2) VALUES(?+1, 2)
-
INSERT INTO s1(i1, i2) VALUES(seq1.nextval, 2)
-
INSERT INTO s1(i1, i2) VALUES((SELECT 1 FROM dual), 2)
여러 노드에 걸쳐 있는 복제 분산 테이블의 경우 다중 노드에 수행한다.
- INSERT INTO c1(i1) VALUES (?)
구문#
INSERT INTO s1 VALUES(1, 2);
예제#
<질의> s1테이블에 insert를 수행하라.
INSERT INTO s1 VALUES(1, 2);
제약 사항#
- 다중 테이블 삽입절은 사용할 수 없다.
- 다중 로우 삽입절은 사용 할 수 없다.
INSERT SELECT#
Insert select문은 항상 다중 노드 수행 쿼리이므로 내부 커넥션으로 수행된다.Insert select문을 이용하면 다른 분산 테이블에 데이터를 복사할 수 있다.
구문#
INSERT INTO s2 SELECT * FROM s1;
예제#
<질의> 분산 테이블 s1의 데이터를 분산 테이블 s2에 복사하라.
INSERT INTO s2 SELECT * FROM s1;
UPDATE#
조건절에 따라 UPDATE 문을 단일 노드 수행 쿼리와 다중 노드 수행 쿼리로 나눈다. 샤드 키 컬럼은 update할 수 없다.
구문#
UPDATE s1 SET i1=3 WHERE k1=1;
예제#
<질의> s1테이블의 k1컬럼이 1인 레코드에 대해 i1컬럼을 3으로 update하라.
UPDATE s1 SET i1=3 WHERE k1=1;
<질의> s1테이블의 i1컬럼을 모두 3으로 update하라.
UPDATE s1 SET i1=3;
DELETE#
조건절에 따라 DELETE 문을 단일 노드 수행 쿼리와 다중 노드 수행 쿼리로 나눈다.
구문#
DELETE FROM s1 WHERE k1=1;
예제#
<질의> s1테이블에서 k1 칼럼의 값이 1인 레코드를 삭제한다.
DELETE FROM s1 WHERE k1=1;
SELECT#
Select문은 조건절에 따라 수행방법이 영향을 받는다.
구문#
SELECT * FROM s1 WHERE k1=1;
예제#
<질의> s1테이블의 k1칼럼의 값이 1인 레코드를 조회한다.
SELECT * FROM s1 WHERE k1=1;
주의 사항#
Select문은 사용 유형이 다양한 만큼 그 수행 여부에 영향을 줄 수 있는 요소가 많다.
Altibase Sharding은 샤드 테이블에 대해 다음과 같은 유형을 지원한다.
-
Join
-
Aggregate function
-
Grouping
-
Ordering
-
Subquery
Join#
Select 시 샤드 테이블에 다음과 같은 형태의 join구문을 지원한다.
Inner join#
동일한 샤드 키 분산 방식이 적용된 샤드 테이블(s1,s2)간의 샤드 키 inner join을 지원한다.
- SELECT \~ FROM s1, s2 WHERE s1.k1 = s2.k1
Join 구문 역시 쿼리 최적화를 통해 수행되기 때문에 샤드 키를 필터로 적용할 경우 샤드 키에 해당하는 노드로 샤드 라이브러리 커넥션을 생성하여 해당 노드에 직접 수행한다. 하지만 샤드 키 필터를 적용하지 않을 경우 내부 커넥션을 생성하여 모든 노드에 수행한 후 샤드 코디네이터가 그 결과를 취합하여 사용자에게 전달한다.
-
SELECT \~ FROM s1, s2 WHERE s1.k1 = s2.k1 AND [s1.k1|s2.k1] = ?
=> 샤드 라이브러리 커넥션으로 특정 노드에 직접 수행 -
SELECT \~ FROM s1, s2 WHERE s1.k1 = s2.k1 AND [s1.i1|s2.i1] = ?
=> 내부 커넥션으로 모든 노드를 수행하고 취합 후 전달 받음
복제 분산 테이블(c1)의 경우 모든 샤드 테이블(s1,c1,so1)에 대해 inner join을 지원한다.
-
SELECT \~ FROM c1, s1 WHERE c1.i1 = s1.i1
-
SELECT \~ FROM c1, so1 WHERE c1.i1 = so1.i1
독립 분산 테이블(so1)과 복제 분산 테이블(c1)의 inner join시 특정 노드를 지정하는 독립 분산 테이블(so1)의 특성상 필터의 유무와 무관하게 샤드 라이브러리 커넥션으로 동작한다.
-
SELECT \~ FROM c1, so1 WHERE c1.i1 = so1.i1
-
=> 샤드 라이브러리 커넥션으로 특정 노드로 직접 수행
Outer join#
동일한 샤드 키 분산 방식이 적용된 샤드 테이블(s1,s2)간의 샤드 키 outer join을 지원한다.
-
SELECT \~ FROM s1 LEFT OUTER JOIN s2 ON s1.k1 = s2.k1
-
SELECT \~ FROM s1 RIGHT OUTER JOIN s2 ON s1.k1 = s2.k1
-
SELECT \~ FROM s1 FULL OUTER JOIN s2 ON s1.k1 = s2.k1
샤드 키 분산 테이블(s1)과 복제 분산 테이블(c1)의 경우 아래 유형에 한해 지원한다.
- SELECT \~ FROM s1 LEFT OUTER JOIN c1 ON c1.i1 = s1.i1
복제 분산 테이블(c1)과 독립 분산 테이블(so1)간의 모든 outer join 을 지원한다.
-
SELECT \~ FROM c1 LEFT OUTER JOIN so1 ON c1.i1 = so1.i1
-
SELECT \~ FROM c1 RIGHT OUTER JOIN so1 ON c1.i1 = so1.i1
-
SELECT \~ FROM c1 FULL OUTER JOIN so1 ON so1.i1 = c1.i1
Outer join이 inner join으로 변환될 경우를 지원한다. 다음 쿼리는 쿼리 변환기를 거쳐 inner join으로 변환되어 수행한다.
- SELECT \~ FROM s1 RIGHT OUTER JOIN c1 ON c1.i1 = s1.i1 WHERE s1.i1 =1
=> SELECT \~ FROM s1 INNER JOIN c1 ON c1.i1 = s1.i1 WHERE s1.i1 = 1
Semi- join#
동일한 샤드 키 분산 방식이 적용된 샤드 테이블(s1,s2)간의 semi-join을 지원한다.
- SELECT \~ FROM s1 WHERE EXISTS (SELECT \~ FROM s2 WHERE s1.k1 = s2.k1 AND \~) AND \~
복제 분산 테이블(c1)의 경우 모든 샤드 테이블에 대해 semi-join을 지원한다.
-
SELECT \~ FROM c1 WHERE EXISTS (SELECT \~ FROM s1 WHERE c1.i1 = s1.i1 AND \~) AND \~
-
SELECT \~ FROM s1 WHERE EXISTS (SELECT \~ FROM c1 WHERE c1.i1 = so1.i1 AND \~) AND \~
Aggregate function#
Altibase Sharding 은 샤드 테이블에 대해 아래 집계 함수를 지원한다.
-
COUNT
-
MIN
-
MAX
-
SUM
-
AVG
-
STDDEV
-
VARIANCE
샤드 키 분산 테이블의 경우 분산 데이터의 특성상 노드 각각에 대해 집계를 수행하므로 그 결과는 모든 데이터의 집계 결과와 논리적으로 같을 수 없다. 따라서 샤드 키 분산 테이블(s1)의 경우 샤드 키 컬럼으로 필터링 되는 경우에 한해 지원한다.
-
SELECT count(*) FROM s1 WHERE k1 = ? \~
-
SELECT sum(k1) FROM s1 WHERE k1 = ? \~
특정 샤드 노드에서 동작하는 복제 분산 테이블(c1)과 독립 분산 테이블(so1)은 일반 테이블의 경우와 동일하게 수행한다.
-
SELECT count(*) FROM c1\~
-
SELECT sum(k1) FROM so1 \~
Grouping#
Altibase Sharding은 샤드 테이블에 대해 다음 grouping 방식을 지원한다.
-
GROUP BY 구문
-
DISTINCT 구문
샤드 키 분산 테이블(s1)에서 샤드 키 컬럼을 grouping 대상으로 포함하는 모든 구문을 지원한다.
-
SELECT \~ FROM s1 \~ GROUP BY k1,\~
-
SELECT distinct k1,\~ FROM s1 \~
-
SELECT distinct k1,\~ FROM s1 \~ GROUP BY k1,\~
특정 노드에서 동작하는 복제 분산 테이블(c1)과 독립 분산 테이블(so1)은 별다른 제약없이 수행된다.
-
SELECT \~ FROM c1 \~ GROUP BY \~
-
SELECT distinct \~ FROM c1 \~
-
SELECT distinct \~ FROM so1 \~ GROUP BY \~
Ordering#
Altibase Sharding 은 샤드 테이블(s1, c1, so1)에 대해 순차적 정렬 방식을 지원한다.
-
SELECT \~ FROM s1 \~ORDER BY \~
-
SELECT \~ FROM c1 \~ORDER BY \~
-
SELECT \~ FROM so1 \~ORDER BY \~
Subquery#
Altibase Sharding 은 샤드 테이블을 포함하는 subquery 유형을 지원한다.
-
INSERT SELECT
-
Inline view
-
Subquery expression
INSERT SELECT#
INSERT에 사용되는 샤드 테이블의 subquery 형태를 지원한다.
-
INSERT \~ SELECT \~ FROM s1 \~
-
INSERT \~ SELECT \~ FROM c1 \~
-
INSERT \~ SELECT \~ FROM so1 \~
Inline view#
From 절에 사용되는 샤드 테이블의 inline view 형태를 지원한다.
-
SELECT \~ FROM (SELECT \~ FROM s1 \~) s, \~
-
SELECT \~ FROM (SELECT \~ FROM c1 \~) c, \~
-
SELECT \~ FROM (SELECT \~ FROM so1 \~) so, \~
Subquery expression#
샤드 키 분산 테이블(s1)을 사용한 subquery를 expression 형태로 사용할 경우에는 샤드 키에 대한 필터가 반드시 존재해야 한다. 이는 subquery expression의 결과가 single row여야 하고 grouping에 대한 샤드 키 필터가 존재해야 하는 이유와 동일하다.
-
SELECT (SELECT \~ FROM s1 WHERE s1.k1 = ?) FROM \~
-
SELECT \~ FROM t1 WHERE t1.i1 = (SELECT max(i1) FROM s1 WHERE s1.k1 = ?)
-
SELECT i1 FROM t1 WHERE i1 in (select k1 from s1)
-
SELECT i1 FROM t1 WHERE i1 in (select i1 from s1)
Subquery 내부에서 사용된 복제 분산 테이블(c1)과 독립 분산 테이블(so1)은 필터의 제한 없이 수행 가능하다.
-
SELECT (SELECT \~ FROM c1) FROM t1 \~
-
SELECT \~ FROM t1 WHERE t1.i1 = (SELECT max(i1) FROM so1)
복제 분산 테이블(c1)이 사용된 subquery는 샤드 테이블(s1,c1,so1)인 외부 컬럼과의 subquery join식을 지원한다.
-
SELECT * FROM s1 WHERE k1 in (SELECT i1 FROM c1)
-
SELECT * FROM s1 WHERE s1.i1 in (SELECT i1 FROM c1 GROUP BY i1)
-
SELECT * FROM so1 WHERE i1 = (SELECT i1 FROM c1 WHERE i1 = so1.i1)
-
SELECT * FROM c1 a WHERE a.i1 = (SELECT min(i1) FROM c1 WHERE i1 = a.i1)
제약 사항#
분산 키 적용 테이블(s1, ss1)간의 subquery join 식은 지원하지 않는다.
- SELECT \~ FROM s1 WHERE s1.k1 in (SELECT k1 FROM ss1)
분산 키 적용 테이블(s1)과 독립 분산 테이블(so1)의 subquery join식은 지원하지 않는다.
- SELECT \~ FROM s1 WHERE s1.k1 in (SELECT i1 FROM so1)
샤드 테이블이 사용된 subquery는 일반 테이블의 외부 컬럼과 join 식을 지원하지 않는다.
-
SELECT i1 FROM t1 WHERE i1 in (SELECT k1 FROM s1 WHERE k1 = t1.i1)
-
SELECT * FROM t1 WHERE i1 = (SELECT i1 FROM c1 WHERE i1 = t1.i1)
-
SELECT * FROM t1 WHERE exists (SELECT i1 FROM so1 WHERE i1 = t1.i1)
Unnesting, view merge 등의 서브 쿼리에 대한 변환이 수행될 경우 변환 결과에 따라 그 수행 여부가 결정된다.
샤드 키워드#
사용자는 특정 노드의 현재 데이터 상태를 확인하거나 특정 노드의 데이터를 취합하는 것을 원할 수 있다.
Altibase Sharding은 사용자의 요구사항을 처리하기 위해 샤드 메타, 코디네이터 또는 샤드 데이터(저장소) 역할로 특정 샤드 노드에 쿼리를 전송하고 그 수행 결과를 취합할 수 있는 샤드 키워드를 제공하며 iSQL 을 통해 사용 가능하다.
구문#
샤드 키워드별로 아래 구문에 한해 제공하며 구문식은 다음과 같다.
- SHARD
- INSERT, UPDATE, DELETE
- SELECT
- NODE[META]
- INSERT, UPDATE, DELETE
- SELECT
- NODE[DATA | DATA() | DATA('node1_name', 'node2_name'...)]
- SELECT

shard_keyword_clause::=

SHARD#
SHARD 키워드를 사용하면 샤드 쿼리 분석기를 통해 쿼리에 존재하는 샤드 객체 분산 정보가 존재하는 모든 샤드 노드에 쿼리를 전송하고 수행하여 취합한다.
각 노드의 데이터를 취합한 결과가 논리적으로 동일할 수 없는 즉, 샤드 쿼리가 아닌 다음의 사례를 살펴보자.
- SELECT count(*) FROM s1;
일반 쿼리에 SHARD 키워드를 적용하면 분산 정보가 존재하는 모든 노드를 대상으로 쿼리를 수행하고 그 결과를 얻어온다.
-
SHARD SELECT count(*) FROM s1;
-
SELECT * FROM SHARD( SELECT count(*) FROM s1);
아래와 같은 형태를 적절히 활용하면 사용자가 원하는 유용한 결과를 얻을 수 있다.
-
SELECT sum(cn) FROM SHARD ( SELECT count(*) cn FROM s1);
-
SELECT i1, sum(cn) FROM SHARD (SELECT i1, count(*) cn FROM s1) GROUP BY i1;
-
SELECT * FROM SHARD (SELECT * FROM s1 limit 10) limit 10;
구문#
SHARD SELECT * FROM s1 WHERE k1>1;
SELECT * FROM SHARD(SELECT * FROM s1 WHERE k1>1);
예제#
<질의> s1테이블의 전체 레코드 개수를 구하라.
SELECT sum(cn) FROM SHARD(SELECT count(*) cn FROM s1);
NODE#
NODE 키워드는 인자로 명시한 노드에 쿼리를 전송하고 그 수행 결과를 취합한다. 샤드 쿼리 분석기를 통하지 않고 해당 쿼리를 바로 전달한다.
사용 가능한 NODE 유형은 다음과 같다.
- NODE[META] : 코디네이팅 샤드 노드에 대한 쿼리 수행
- NODE[DATA] 또는 NODE[DATA()] : 모든 샤드 노드들에 대해 쿼리 분석 및 변환없이 수행
- NODE[DATA('node1_name', node2_name',...)] : 명시된 노드(들)에 대해 쿼리 분석 및 변환없이 수행
노드를 구성하고 샤드 객체 구성 전 후의 데이터 상태를 확인할 경우에 유용하게 쓰일 수 있다.
구문#
NODE[META] SELECT count(*) FROM t1;
NODE[DATA] SELECT count(*) FROM s1;
SELECT * FROM NODE[META](SELECT count(*) FROM s1);
SELECT * FROM NODE[DATA]('node1', 'node2')](SELECT count(*) FROM s1);
<질의> 코디네이팅 샤드 노드에 존재하는 t2테이블의 레코드 개수를 구하라.
CREATE TABLE t2 AS SELECT * FROM s1
EXEC dbms_shard.set_shard_table('sys','t2','H','i1');
EXEC dbms_shard.set_shard_hash('sys','t2',1000,'node1');
NODE[META] SELECT count(*) FROM t1;
<질의> 'node2' 에 존재하는 s1 샤드 테이블에 대해 샤드키가 아닌 i1 컬럼의 group별 합을 수행하라.
SELECT * FROM NODE[DATA('node2')](SELECT i1,sum(i1) FROM s1 GROUP BY i1);
![CAUTION]
샤드 키워드는 iSQL 을 통한 관리 목적으로 사용해야 한다.
샤드 키워드의 적용 결과가 단순히 해당 노드의 수행 결과를 얻어 취합하는 것이므로 결과의 정합성을 보장하지 않는다. 따라서 사용에 각별한 주의가 필요하다.
샤드 함수#
Altibase Sharding은 사용자 편의를 위해 추가적인 샤드 함수를 제공한다.
shard_node_name#
구문#
shard_node_name()
설명#
샤드 노드의 이름을 반환한다.
예제#
<질의> 샤드 노드 별 s1테이블의 레코드 개수를 구하라.
shard SELECT shard_node_name(),count(*) FROM s1;
shard_key#
구문#
shard_key(key_column, value)
설명#
샤드 노드를 지정하여 질의를 수행한다.
예제#
<질의> s1테이블의 k1이 1에 해당하는 샤드 노드에서 s1테이블의 레코드 개수를 구하라.
SELECT count(*) FROM s1 WHERE shard_key(k1,1);
샤드 실행계획#
Altibase Sharding 사용자는 iSQL을 통해 쿼리가 수행되는 실행계획을 조회할 수 있다.
샤드 최적화기가 생성한 실행계획과 샤드 노드에서 생성한 실행계획을 모두 조회할 수 있으며 쿼리를 분석하여 최적화 하는데 사용할 수 있다.
일반적으로 Altibase Sharding에서 사용되는 논샤드 쿼리는 가능한 샤드 쿼리로 변경하여 사용하는 것이 성능상 유리하다.
실행 노드 확인#
샤드 최적화기가 생성한 실행노드의 기능과 explain plan으로 출력되는 형식, 해당 노드가 출력되는 쿼리 예제를 살펴본다.
출력 형식#
SHARD-COORDINATOR
설명#
SHARD-COORDINATOR 실행노드는 사용자가 입력한 쿼리 중 샤드 노드에서 수행할 쿼리를 수행하고, 그 결과를 통합하여 상위 실행노드로 전달한다.
보다 상세한 수행 결과를 조회하기 위하여 다음 명령을 사용한다.
ALTER SESSION SET TRCLOG_DETAIL_PREDICATE = 1;
TRCLOG_DETAIL_PREDICATE 프로퍼티 값을 1로 설정하면, SHARD-COORDINATOR가 특정 샤드 노드로 쿼리를 보내어 수행한 이력 및 플랜을 조회할 수 있다.
다음은 쿼리 문의 실행 결과 출력이다.
alter session set explain plan = on;
Alter success.
alter session set trclog_detail_predicate = 1;
Alter success.
select * from t1, t2 where t1.i1=t2.i1;
I1 I2 I1 I2
-----------------------------------------------------
7 test1 7 test2
10 test1 10 test2
1 test1 1 test2
3 test1 3 test2
5 test1 5 test2
6 test1 6 test2
8 test1 8 test2
2 test1 2 test2
4 test1 4 test2
9 test1 9 test2
10 rows selected.
------------------------------------------------------------
PROJECT ( COLUMN_COUNT: 4, TUPLE_SIZE: 32, COST: 1174.86 )
SHARD-COORDINATOR
[ SHARD EXECUTION ]
NODE1 (executed)
::-----------------------------------------------------------
::PROJECT ( COLUMN_COUNT: 4, TUPLE_SIZE: 32, COST: 6339.74 )
:: JOIN ( METHOD: INDEX_NL, COST: 935.45 )
:: SCAN ( TABLE: SYS.T1, FULL SCAN, ACCESS: 2, COST: 116.76 )
:: SCAN ( TABLE: SYS.T2, INDEX: SYS.IDX2, RANGE SCAN, ACCESS: 2, COST: 116.76 )
::-----------------------------------------------------------
NODE2 (executed)
::-----------------------------------------------------------
::PROJECT ( COLUMN_COUNT: 4, TUPLE_SIZE: 32, COST: 6339.74 )
:: JOIN ( METHOD: INDEX_NL, COST: 935.45 )
:: SCAN ( TABLE: SYS.T1, FULL SCAN, ACCESS: 5, COST: 116.76 )
:: SCAN ( TABLE: SYS.T2, INDEX: SYS.IDX2, RANGE SCAN, ACCESS: 5, COST: 116.76 )
::-----------------------------------------------------------
NODE3 (executed)
::-----------------------------------------------------------
::PROJECT ( COLUMN_COUNT: 4, TUPLE_SIZE: 32, COST: 6339.74 )
:: JOIN ( METHOD: INDEX_NL, COST: 935.45 )
:: SCAN ( TABLE: SYS.T1, FULL SCAN, ACCESS: 3, COST: 116.76 )
:: SCAN ( TABLE: SYS.T2, INDEX: SYS.IDX2, RANGE SCAN, ACCESS: 3, COST: 116.76 )
::-----------------------------------------------------------
------------------------------------------------------------
샤드 쿼리 분석#
Altibase Sharding 은 isql을 통해 사용자 구문에 대한 샤드 쿼리 분석 결과를 확인하는 방법을 제공하며 다음과 같은 조건하에 동작한다.
- alter session set EXPLAIN PLAN = ON (or ONLY);
- alter session set TRCLOG_DETAIL_SHARD = 1;
단, TRCLOG_DETAIL_SHARD=1 의 경우 내부적으로 cache 된 plan을 사용하지 않고 새로이 plan을 생성하므로 사용상 주의가 필요하다.
ANALYSIS COST#
샤드 쿼리 분석의 최소단위는 쿼리 구문이며 샤드 쿼리 분석기는 구문 단위의 분석을 수행한다.
주어진 구문에 대해 분석을 수행하고 구문 변환을 시도한 후 다시 반복해서 구문 분석을 시도한다.
샤드 쿼리 분석 비용은 사용자 구문에 대해 시도한 총 분석 횟수로 계산된다.
QUERY TYPE#
사용자 쿼리는 다음과 같이 구분할 수 있다.
- 샤드 쿼리(Shard query) : 분산 수행 결과와 단일 수행 결과의 정합성이 보장되는 구문
- 논샤드 쿼리(Non-shard query) : 분산 수행 결과와 단일 수행 결과의 정합성이 보장되지 않는 구문
샤드 라이브러리를 연동한 경우라면 샤드 쿼리는 클라이언트측 샤딩을 수행하고 논샤드 쿼리는 서버측 샤딩을 수행한다.
NON-SHARD QUERY REASON#
사용자 쿼리를 논샤드 쿼리로 분석한 이유이다.
QUERY TRANSFORMABLE#
사용자 쿼리가 논샤드 쿼리로 분류된 경우라면 서버측 샤딩을 수행하게 된다.
샤드 쿼리 최적화기는 해당 쿼리를 서버측에서 수행하기 위해 샤드 쿼리 변환을 통해 최적의 분산부 쿼리 생성을 시도하는데 이 경우 최적화된 분산부 쿼리 생성 가능성을 다음과 같이 표현한다.
- 변환된 분산부 쿼리 생성이 가능하면 'Yes'
- 변환된 분산부 쿼리 생성이 불가하면 'No'
쿼리 분석 예제#
다음은 분산된 샤드 테이블 s1에 대한 샤드 쿼리분석 결과이다.
Print shard analysis information Example
alter session set explain plan = only;
Alter success.
alter session set trclog_detail_shard = 1;
Alter success.
SELECT * FROM s1;
I1 I2 I3
----------------------------------------
No rows selected.
------------------------------------------------------------
PROJECT ( COLUMN_COUNT: 3, TUPLE_SIZE: 20, COST: BLOCKED )
SHARD-COORDINATOR
------------------------------------------------------------
[ SHARD ANALYSIS INFORMATION ]
ANALYSIS COST : 1
SHARD QUERY TYPE : Shard query
------------------------------------------------------------
SELECT count(*) FROM s1;
COUNT(*)
-----------------------
No rows selected.
------------------------------------------------------------
PROJECT ( COLUMN_COUNT: 1, TUPLE_SIZE: 8, COST: BLOCKED )
GROUP-AGGREGATION ( ITEM_SIZE: ??, GROUP_COUNT: ??, BUCKET_COUNT: 1, ACCESS: ??, COST: BLOCKED )
SHARD-COORDINATOR
[ DISTRIBUTION QUERY ]
SELECT COUNT(*) FROM S1;
------------------------------------------------------------
[ SHARD ANALYSIS INFORMATION ]
ANALYSIS COST : 3
QUERY TYPE : Non-shard query
NON-SHARD QUERY REASON : GROUP BY needed multiple nodes.
QUERY TRANSFORMABLE : Yes
------------------------------------------------------------
쿼리 튜닝#
Altibase Sharding은 샤드 쿼리로 적용되지 않는 복잡한 논샤드 쿼리를 변환없이 사용할 수 있다는 장점이 있으나 논샤드 쿼리는 샤드 코디네이터의 처리 과정을 거치게 되므로 성능 저하를 유발할 수 있다.
그러므로, 샤딩 시스템을 좀 더 효율적으로 사용하기 위해서 샤드 키워드를 이용하여 쿼리를 튜닝하면 성능을 획기적으로 개선할 수 있다.
Grouping#
grouping의 키로 샤드 키가 포함된 경우 샤드 쿼리 분석기는 샤드 쿼리로 판단한다.
그러나 grouping key에 샤드 키가 포함되지 않으면, 샤드 코디네이터가 전체 데이터를 수집하여 처리하므로 성능 저하의 원인이 될 수 있다. 이런 경우 grouping을 각 샤드 노드에서 수행하도록 변경하면 샤드 노드의 부하도 줄고 쿼리 속도도 빨라진다.
SELECT c1, count(*), sum(i2), avg(i2) FROM s1 GROUP BY c1;
위의 쿼리에 다음과 같이 SHARD 키워드를 사용하여 변경할 수 있다.
SELECT c1, sum(c), sum(s), sum(s)/count(a) FROM SHARD(SELECT c1, count(*) c, sum(i2) s, count(i2) a FROM s1 GROUP BY c1) GROUP BY c1;
Pushdown#
서로 다른 분산방식의 테이블을 조인하는 경우, 조인은 샤드 코디네이터가 수행하게 된다.
이 때, 조인 비용을 줄이기 위해서 조건절을 샤드 노드에서 수행하도록 변경하면 샤드 코디네이터를 거치지 않아 쿼리 속도가 빨라진다.
다음과 같은 쿼리가 있다.
SELECT * FROM t1, t2 WHERE t1.i1=t2.i1 AND t1.i2>3;
이를 SHARD 키워드를 사용하여 다음과 같이 변경할 수 있다.
SELECT * FROM SHARD(SELECT * FROM T1 WHERE I2>3) t1, t2 WHERE t1.i1=t2.i1;
모니터링#
Altibase Sharding 사용자는 샤딩 시스템에서 제공하는 샤드 성능 뷰를 이용하여 모든 샤드 노드의 수행 상태를 확인할 수 있다.
모든 샤드 노드에 대해 쿼리를 동시에 수행하므로 샤딩 시스템의 모든 샤드 노드를 한번에 관찰하기에 유용하다.
샤드 성능 뷰는 내부적으로 NODE 키워드를 이용하여 모든 샤드 노드의 성능 뷰 정보와 그 외 추가적인 정보를 취합하여 생성된다. 따라서 노드의 상태에 따라 쿼리가 실패할 수도 있다.
Property 조회#
S\$PROPERTY를 이용하여 샤딩 시스템에서 사용되는 모든 노드의 시스템 프로퍼티를 확인할 수 있다.
예를 들어 모든 샤드 노드의 PORT_NO 를 확인하는 방법은 다음과 같다.
SELECT node_name, value1 from s$property WHERE name = 'PORT_NO';
NODE_NAME VALUE1
-----------------------------------------------
NODE1 20030
NODE2 21030
NODE3 22030
3 rows selected.
Session 조회#
S$SESSION을 이용하여 모든 샤드 노드의 모든 샤드 세션을 확인할 수 있다.
다음은 모든 샤드 세션을 확인하는 방법이다.
SELECT id, node_name, session_id, shard_client, shard_session_type FROM s$session;
ID NODE_NAME SESSION_ID SHARD_CLIENT SHARD_SESSION_TYPE
----------------------------------------------------------------------------------------------
1-1-1701180354 NODE1 2 N U
1-1-1701180354 NODE1 1 N C
1-1-1701180354 NODE2 1 N C
1-1-1701180354 NODE3 1 N C
4 rows selected.
Statement 조회#
S$STATEMENT를 이용하여 모든 샤드 세션에서 실행되는(또는 가장 최근 실행된) 구문을 확인할 수 있다.
다음은 모든 샤드 세션에서 수행되는 모든 구문을 확인하는 방법이다.
SELECT shard_session_id, node_name, shard_session_type, session_id, id, query_type, substr(query, 1, 6) FROM s$statement;
SHARD_SESSION_ID NODE_NAME SHARD_SESSION_TYPE SESSION_ID ID QUERY_TYPE SUBSTR(QUERY, 1, 6)
------------------------------------------------------------------------------------------------------------------------
1-1-1701180354 NODE1 C 1 65538 - SELECT
1-1-1701180354 NODE1 U 2 131072 N SELECT
1-1-1701180354 NODE2 C 1 65538 - SELECT
1-1-1701180354 NODE3 C 1 65538 - SELECT
4 rows selected.
주의사항#
특정 노드의 장애로 인해 샤드 성능 뷰로 조회가 불가능할 경우 NODE 키워드를 이용하여 다른 노드의 상태를 확인할 수 있다.
NODE[DATA(‘node1’)] SELECT shard_node_name(), QUERY_TIME_LIMIT FROM v$session;
Fail-Over#
Altibase Sharding의 Fail-Over기능은 특정 샤드 노드에 장애가 발생 하였을 때, 해당 노드의 가용(Alternate) 서버로 자동 전환되는 기능이며 샤드 노드 설정 및 응용 프로그램 설정을 통해서 사용 가능하다.
Altibase Sharding의 Fail-Over를 이해하기 위해서는 Sharding에서 사용하는 각 커넥션에 대한 이해가 선행되어야 한다.
- 사용자 커넥션(User Connection)
- 샤드 라이브러리 커넥션(Shard Library Connection)
- 코디네이터 커넥션(Coordinator Connection)
Altibase Sharding에서는 각 커넥션의 연결 장애 시 Fail-Over가 발생할 수 있다.
각 커넥션에 대한 Fail-Over는 장애를 인식하는 시점에 따라 CTF (Connection Time Fail-Over)와 STF (Service Time Fail-Over)로 분류할 수 있으며, 커넥션 마다 Fail-Over의 동작이 다르므로 각 커넥션에 대한 Fail-Over 동작을 이해해야 한다.
Altibase Sharding에서의 Fail-Over는 다수의 샤드 노드에 대한 커넥션에 대해서 고려해야하므로 응용 프로그램 처리 가이드에 따라 처리할 것을 권장한다.
Fail-Over에 대한 개요 및 사용 방법은 Altibase Replication Manual을 참고한다.
사용자 커넥션#
사용자 커넥션에 대한 Fail-Over는 응용 프로그램에서 API의 연결 함수 호출시 입력한 연결 속성 문자열에 명시하거나 연결 설정 파일에 명시한 샤드 노드의 IP, PORT로 시도한다.
사용자 커넥션에 대한 Fail-Over는 Replication환경에서 Altibase Fail-Over의 사용법과 동일하며, Replication환경에서 Altibase Fail-Over의 사용법은 Altibase Replication Manual을 참고한다.
샤드 라이브러리 커넥션#
샤드 라이브러리 커넥션은 사용자 커넥션 연결 시에 샤드 라이브러리에서 자동으로 샤드 노드에 접속하는 것을 말한다.
Fail-Over는 시스템 관리자가 등록한 샤드 노드의 외부 커넥션 IP,PORT로 시도한다.
예를들어, 관리자가 NODE1을 다음과 같은 프로시저를 통해서 설정할 수 있다.
EXEC dbms_shard.set_node('node1', '192.168.1.30', 20300, '192.168.1.31', 20400);
Execute success.
위의 예제에서 NODE1의 샤드 라이브러리 커넥션은 “'192.168.1.30', 20300”에 연결을 시도하며 문제 발생시 “'192.168.1.31', 20400”으로 Fail-Over 시도한다.
샤드 라이브러리 커넥션에 대한 Fail-Over설정을 변경하기 위해서는 다음의 프로시저를 통해서 변경 가능하다.
EXEC dbms_shard.reset_node_external('node1', '192.168.100.1', 20300, '192.168.100.2', 20300);
Execute success.
만약, 샤드 라이브러리 커넥션의 통신 방법을 커넥션 별로 변경하고 싶은 경우 사용자 커넥션의 커넥션 스트링에 SHARD_CONNTYPE 속성으로 지정 가능하다. 지원 타입은 Altibase Sharding 통신 방법의 샤드 라이브러리 커넥션을 참고한다.
제약 사항#
- Altibase Sharding에서 Fail-Over 콜백 함수는 사용자 커넥션에 대해서만 동작하며 샤드 라이브러리 커넥션에 대한 Fail-Over 콜백 함수는 지원하지 않는다.
코디네이터 커넥션#
코디네이터 커넥션에 대한 Fail-Over는 시스템 관리자가 등록한 샤드 노드의 내부 커넥션 IP, PORT로 시도한다.
예를들어, 관리자가 NODE1을 다음과 같은 프로시저를 통해서 설정할 수 있다.
EXEC dbms_shard.set_node('node1', '192.168.1.30', 20300, '192.168.1.31', 20400);
Execute success.
위의 예제에서 NODE1의 코디네이터 커넥션은 “'192.168.1.30', 20300”에 연결을 시도하며 문제 발생시 “'192.168.1.31', 20400”으로 Fail-Over 시도한다.
코디네이터 커넥션에 대한 Fail-Over설정을 변경하기 위해서는 다음의 프로시저를 통해서 변경 가능하다.
EXEC dbms_shard.reset_node_internal('node1', '192.168.100.11', 20300,
'192.168.100.12', 20300);
Execute success.
코디네이터 커넥션의 Fail-Over 동작은 다음의 프로퍼티를 통해서 세부적으로 설정 가능하다. 각 프로퍼티의 세부 설명은 이 문서의 프로퍼티 설명을 참조한다.
- SHARD_INTERNAL_CONN_ATTR_RETRY_COUNT
- SHARD_INTERNAL_CONN_ATTR_RETRY_DELAY
- SHARD_INTERNAL_CONN_ATTR_CONNECTION_TIMEOUT
- SHARD_INTERNAL_CONN_ATTR_LOGIN_TIMEOUT
응용 프로그램 가이드#
Altibase Sharding 환경에서는 여러 샤드 노드에서 수행중인 트랜잭션 및 커넥션이 있으며, 이들은 최적화 과정을 거쳐서 샤드 라이브러리 혹은 서버에서 내부적으로 처리된다. 그러므로 특정 노드의 장애나 접속 에러 시에도 일부 커넥션이 남아 있거나 트랜잭션이 완전히 철회되지 않을 수 있다.
이러한 분산 환경에서 응용 프로그램이 트랜잭션 처리를 일관되게 하기 위해서는 NON-AUTOCOMMIT을 사용하여 다음의 가이드에 따라 작성되어야 Fail-Over가 정상적으로 처리될 수 있다.
다만, 응용 프로그램이 다수의 샤드 노드를 접근하지 않도록 설계된 경우에는 AUTOCOMMIT 모드를 사용할 수 있으나 이 경우에도 AUTOCOMMIT에 대한 가이드에 따라 처리되어야 Fail-Over 이후에 서비스가 정상적으로 처리될 수 있다.
CTF(Connection Time Failover)#
CTF의 경우에는 데이터 베이스 연결이 되는지에 따라 성공 여부를 바로 알 수 있다.
다만, 분산 환경에서는 일부 노드의 에러로 인해 실패했을 때, 일부 노드에 접속 되어있을 수 있으므로 명시적으로 SQLDisconnect를 호출하여 전체 연결을 끊어 주어야 한다.
CTF는 트랜잭션이 시작되기 전에 발생하므로 Commit 모드는 고려하지 않아도 된다.
STF(Service Time Failover)#
ShardCLI 경우는 SQLPrepare, SQLExecute, SQLFetch등에서 SQL_SUCCESS가 아닌 에러가 발생하면, SQLGetDiagRec에 statement 핸들을 넘기고, 이 함수의 5번째 인자에 반환되는 native 에러 코드 값이 ALTIBASE_FAILOVER_SUCCESS인 진단 레코드(diagnostic record)가 있으면 STF가 성공한 것으로 판단할 수 있다.
- NON-AUTOCOMMIT 트랜잭션
ShardCLI 함수에서 SQL_SUCCESS가 아닌 에러가 발생하였을 때 다음의 순서로 에러 로직을 처리한다.
- STF가 성공한 경우(ALTIBASE_FAILOVER_SUCCESS) Rollback을 수행하며 Rollback이 성공하면 트랜잭션 재시작 위치로 되돌아 가서 응용 프로그램 로직을 수행한다.
- 트랜잭션 재시작 위치는 SQLPrepare,SQLExecute를 사용하는 경우 최초 SQLPrepare 이전으로 돌아가야 하며 Bind는 다시 하지 않아도 된다.
- SQLDirectExec를 사용하는 경우에는 SQLDirectExec 이전으로 돌아가면 된다.
- STF 성공 후 Rollback을 하는 중에 다시 Fail-Over가 발생할 수 있으므로 이 경우에는 Rollback을 한번 더 수행한다.
- STF가 실패하고 더 이상 서비스 가능한 가용 노드가 없는 경우(ALTIBASE_SHARD_NODE_FAILOVER_IS_NOT_AVAILABLE) 전체 노드에 대한 연결을 명시적으로 끊고 최초 연결부터 재시도 한다.
- 샤딩 환경에서는 다수의 노드에 접속이 이뤄져 있으므로 명시적으로 SQLDisconnect를 호출해야 모든 노드에 연결이 끊긴다
-
그 외의 에러에 대해서는 응용 프로그램 에러 처리 로직을 수행한다.
-
AUTOCOMMIT 트랜잭션
ShardCLI 함수에서 SQL_SUCCESS가 아닌 에러가 발생하였을 때 다음의 순서로 에러 로직을 처리한다.
- STF가 성공한 경우(ALTIBASE_FAILOVER_SUCCESS) 트랜잭션 재시작 위치로 되돌아 가서 응용 프로그램 로직을 수행한다.
- 트랜잭션 재시작 위치는 SQLPrepare, SQLExecute를 사용하는 경우 최초 SQLPrepare 이전으로 돌아가야 하며 Bind는 다시 하지 않아도 된다.
- SQLDirectExec를 사용하는 경우에는 SQLDirectExec 이전으로 돌아가면 된다.
- STF가 실패하고 더 이상 서비스 가능한 가용 노드가 없는 경우 (ALTIBASE_SHARD_NODE_FAILOVER_IS_NOT_AVAILABLE) 전체 노드에 대한 연결을 명시적으로 끊고 최초 연결부터 재시도 한다.
- 샤딩 환경에서는 다수의 노드에 접속이 이뤄져 있으므로 명시적으로 SQLDisconnect를 호출해야 모든 노드에 연결이 끊긴다.
ShardCLI Failover Sample Code#
Altibase Sharding의 failover를 포함하는 Shardcli sample 코드는 \$ALTIBASE_HOME/sample/SHARD/Fail-Over/failoversample.cpp에 있으며, 해당 프로그램은 ShardCLI를 이용하여 작성한 fail-over를 고려한 응용 프로그램 예제이다.
failoversample.cpp의 코드는 “CREATE TABLE T1 (I1 VARCHAR(20), I2 INTEGER);”의 구문으로 T1 테이블을 생성한 후 T1 테이블을 샤드 테이블로 등록하였다고 가정한다.
해당 프로그램은 최초 접속할 샤드 노드의 port와 alternate port를 순차적으로 입력받아 연결하고 응용 프로그램 로직을 수행하여 Direct-Execute 방식으로 데이터를 한 건 입력하고 Prepare-Execute 방식으로 질의를 수행한 후 검색된 데이터를 출력하는 프로그램이다.
예제 프로그램을 수행중에 특정 노드에 장애가 있는 경우 최초 접속시에 CTF가 동작하며 실행 중에는 STF를 통해 fail-over 된다.
주의할 점은, 접속을 재시도 하기 위해서는 남아 있을 수 있는 커넥션을 종료하기 위해서 SQLDisconnect를 명시적으로 호출해 주어야 하며, 에러가 발생했을 때에는 다수의 노드에서 발생했을 수 있는 에러를 확인하기 위해서 SQLDiagRec을 통해 모든 노드의 에러를 점검해야 한다.
에러 점검을 통해서 Service Time Fail-over가 되면 연결이 종료되지 않은 샤드 노드에 남아 있는 트랜잭션을 정리하기 위해서 SQLEndTran(ROLLBACK)을 호출해 준 후 다시 Prepare 혹은 DirecExecute 로직으로 돌아가서 수행 한다.
자세한 코드 내용은 \$ALTIBASE_HOME/sample/SHARD/Fail-Over/failoversample.cpp를 참고한다.
샤딩 분산 시스템 변경#
샤딩 시스템 운영중에 데이터 저장소가 부족하거나 서비스 용량이 추가로 필요한 경우 신규 샤드 노드를 추가할 수 있다.
신규 노드가 추가되면 데이터를 이동시켜 부하를 나누어 줄 수 있으며, 이 때 기존 시스템 분석을 통해서 적절한 양의 데이터를 이동 시켜야 한다.
샤딩 시스템을 운영하면서 특정 샤드 노드에 데이터가 집중되는 현상이 발생할 수 있으며, 특정 샤드 노드에 데이터가 집중되면 부하의 불균형을 가져와 전체 시스템 성능이 저하되거나 저장 공간이 부족하여 시스템 운영에 문제를 불러일으킬 수 있다.
이런 문제를 해소하기 위해서 데이터가 집중된 샤드 노드의 데이터를 다른 샤드 노드로 분배해야 한다.
샤드 노드의 구성 변경이나 노드의 일부 하드웨어 장애로 인해서 샤드 노드를 제거하는 경우에도 제거되는 샤드 노드의 데이터를 보존하기 위해서는 운영중인 다른 샤드 노드로 데이터를 옮겨 준 후 샤드 노드를 제거해야 한다.
이 외에도 샤딩 시스템을 재구축 하기 위해서 샤드 키를 변경하는 등의 데이터 재구축 작업을 필요로 할 수 있으며, , 정리하면 샤딩 분산 시스템 변경을 필요로 하는 시점은 다음과 같은 경우이다.
- 샤드 노드 추가
- 샤드 데이터 분포 조정
- 샤드 노드 제거
- 샤딩 데이터 재구축
Altibase Sharding은 이와 같은 다양한 샤딩 시스템 변경에 대한 분산 데이터 이동 방법을 지원하기 위해서 서비스 중에 데이터를 이동시키는 리샤딩과 서비스 중지 후 데이터를 이동시키는 데이터 재구축을 제공한다. 이 외에도 분산 데이터의 정합성을 확인하기 위한 유효성 검사 방법을 제공한다.
- 유효성 검사
- 리샤딩
- 데이터 재구축
리샤딩과 데이터 재구축을 통한 데이터 이동을 비교하면 아래 표와 같다.
| 지원 항목 | 리샤딩 | 데이터 재구축 |
|---|---|---|
| 테이블 종류 | 파티션드 테이블 | 일반 테이블, 파티션드 테이블 |
| 분산 방식 | HASH, RANGE, LIST, SOLO, CLONE | HASH, RANGE, LIST, COMPOSITE |
| 변경 작업 | 동일 분산 방식의 범위 변경 | 분산 방식 변경 및 범위 변경, 샤드 키 변경 |
| 데이터 이동 단위 | 파티션 단위 | 테이블 단위 |
| 서비스 중단 여부 | 서비스 무중단 | 서비스 중단 |
| 대상 노드 | 1 대 1 | 1 대 N, N 대 N |
[표 3]. 리샤딩과 데이터 재구축 기능 비교
노드 추가#
샤딩 시스템에 샤드 노드를 추가하는 방법으로 샤드 매니저를 통한 방법과 수동으로 샤드 노드를 추가하는 방법을 제공한다.
수동으로 노드를 추가하는 것은 DBMS_SHARD 패키지의 SET_NODE 프로시저를 통해서 가능하다.
다만, 수동으로 샤드 노드를 추가하는 경우 기존 샤드 노드와 동일하게 샤드 메타를 복제해야하며, 샤드 메타의 일부가 다른 경우 데이터 서비스가 비정상 적으로 동작할 수 있으므로 권장하지 않는다.
수동으로 샤드 노드를 추가하는 것에 대한 자세한 설명은 본 장의 “샤드 노드” 절을 참고한다.
샤드 매니저를 통해 샤드 노드를 추가하는 경우 자동으로 샤드 메타를 복제하여 샤딩 시스템에 참여할 수 있도록 한다.
샤드 매니저를 통한 샤드 노드 추가는 6장 Altibase Sharding 유틸리티의 Shard Manager 를 참고한다.
주의 사항
노드 추가를 완료해도 해당 노드에 샤드 객체는 생성되어 있지 않으므로 동일한 스키마로 사용자가 샤드 객체를 생성해야한다.
노드 제거#
샤딩 시스템에서 노드를 제거하는 경우는 일반적이지 않으나 해당 노드에 영구적인 장애가 발생하거나 혹은 시스템의 축소를 위해서 노드를 제거할 수 있다.
샤드 노드를 제거하기 위해서는 노드 제거를 위한 데이터 이동 계획을 수립하고 이에 따라 해당 노드에 존재하는 데이터를 다른 샤드 노드로 이동시킨다.
데이터 이동이 완료되면 제거되는 노드에 사용자 커넥션으로 연결된 응용프로그램을 서비스 가능한 다른 샤드 노드로 이동시켜야한다.
그 후, 샤드 노드 추가와 동일하게 샤드 매니저나 DBMS_SHARD 패키지의 UNSET_NODE로 샤드 메타에서 해당 노드를 삭제한다.
샤드 노드 삭제가 시스템에서 인식되면 해당 노드에 존재하는 응용프로그램의 샤드 라이브러리 커넥션이 시간이 경과함에 따라 자동적으로 다른 샤드 노드로 이동한다. 시스템 관리자는 해당 노드의 세션이 모두 종료된 것을 확인하면 더 이상 시스템에 영향을 주지 않으므로 제거가 완료되었다고 볼 수 있다.
샤드 매니저를 통한 샤드 노드 삭제는 6장 Altibase Sharding 유틸리티의 Shard Manager 를 참고하며 DBMS_SHARD 패키지의 UNSET_NODE에 대한 자세한 내용은 본 장의 “샤드 노드” 절을 참고한다.
주의 사항
노드 제거가 완료되도 해당 노드에 샤드 객체를 명시적으로 DROP 하지 않으면 객체가 제거되지 않는다.
유효성 검사#
샤드 테이블의 샤드 키 분산 방식 변경으로 인해 샤드 키와 데이터의 불일치가 발생할 수 있다. 분산 정보가 재설정 된 경우 기존의 분산 데이터는 샤드 키에 유효한(correct) 데이터와 유효하지 않은(incorrect) 데이터로 구분된다.
Altibase Sharding 은 샤드 키 분산 정보와 분산 데이터의 유효성을 검사하는 방법으로 아래와 같은 패키지 프로시저를 제공한다.
DBMS_SHARD.CHECK_DATA
사용 방법은 Altibase Sharding 패키지의 CHECK_DATA 를 참고한다.
데이터 재구축#
Altibase Sharding은 샤드 테이블의 분산 정보를 변경한 후, 기존의 데이터를 재구축하거나 특정 샤드 노드를 지정하여 데이터를 이동시키는 방법을 제공한다.
데이터 재구축을 위해서는 기존 분산 테이블을 해제(unset)한 후, 새로운 분산 방식으로 분산 테이블을 재설정(set)하는 과정을 선행해야 한다. 그러므로 진행중인 관련 테이블을 사용 중인 응용 프로그램을 종료 시킨 후 수행하여야 한다.
성능을 고려하여, 데이터 재구축은 변경된 분산 기준에 맞지 않는 데이터(incorrect data)만 이동(move)시키는 방식으로 수행되며 여러 세션에서 동시에 수행 가능하다. 단, 내부적으로 데이터의 이동이 수반되기 때문에 데이터의 정합성 보장을 위해서는 사용자 어플리케이션을 정지한 이후 수행해야 한다.
데이터 재구축은 샤드 키 분산(hash, range, list, composite) 방식을 적용한 샤드 테이블에 한해 지원하며, 복제 분산 방식과 독립 분산 방식은 지원하지 않는다.
- hash(500,1000) \<-> hash(300,600,1000) (O)
- hash \<-> range (O)
- hash \<-> list,hash (O)
- range \<-> clone (X)
- solo \<-> hash (X)
- clone \<-> solo (X)
Altibase Sharding 은 데이터 재구축 방법으로 아래와 같은 패키지 프로시저를 제공한다.
DBMS_SHARD.REBUILD_DATA
DBMS_SHARD.REBUILD_DATA_NODE
사용 방법은 Altibase Sharding 패키지의 REBUILD_DATA, REBUILD_DATA_NODE 를 참고한다.
리샤딩#
Altibase Sharding의 리샤딩은 서비스 중에 노드를 추가하거나 데이터의 분포가 특정 샤드 노드에 밀집되어있을 때 샤드 노드들의 데이터 범위를 변경하고 데이터를 재분배 하는 것을 말한다.
Altibase Sharding에서 제공하는 리샤딩은 데이터베이스 서비스에 영향을 최소화하여 백그라운드로 진행되므로, 응용 프로그램의 변화나 서비스 중단 없이 수행 가능하다.
서비스의 영향을 최소화 하기 위해서 데이터 이동은 한번에 하나의 샤드 노드에서 다른 하나의 샤드 노드로 이동하며 다수의 노드간 데이터 이동은 유발하지 않는다.
리샤딩은 온라인중에 데이터를 이동하기 위해서 내부적으로 이중화를 사용하며, 트랜잭션의 중단이 발생하지 않도록 Shard Meta Number(SMN)라는 개념을 두어 리샤딩 이전에 접속한 클라이언트와 이후에 접속한 클라이언트가 끊김없이 서비스 가능하도록 지원한다. SMN에 대한 자세한 내용은 2장 Altibase Sharding 설치와 설정의 샤드 메타 설정을 참고한다.
리샤딩은 샤드 테이블의 종류에 따라서 다음과 같이 분류될 수 있고, 샤드 매니저를 통해서 수행할 수 있다. 샤드 매니저의 리샤딩 사용 법에 대한 자세한 설명은 6장 Altibase Sharding 유틸리티의Shard Manager절을 참조한다.
- 단일 샤드 키 분산 테이블 리샤딩
- 복제 분산 테이블 리샤딩
- 독립 분산 테이블 리샤딩
단일 샤드 키 분산 테이블 리샤딩#
단일 샤드 키 분산 테이블의 리샤딩은 샤드 테이블의 파티션 단위로 수행 가능하다.
단일 샤드 키 분산 테이블 리샤딩을 계획할 때 주의해야할 것은 샤딩 시스템으로 요청되는 질의를 잘 고려하여 동일 샤드 키로 처리되는 샤드 테이블 그룹을 함께 이동시켜야 한다는 것이다.
만약, TABLE1과 TABLE2가 ID라는 컬럼으로 동일한 샤드 키와 설정을 가지고 있다면 리샤딩 이후에도 TABLE1과 TABLE2에 대해서 동일한 데이터 분포를 가질 수 있도록 해야한다. 그렇지 않고 TABLE1만 이동하는 경우 TABLE1과 TABLE2를 조인하는 질의가 요청되면 샤드 쿼리라고 하더라도 서버 사이드로 동작하여 성능 저하를 유발할 수 있다.
샤드 데이터 분포 조정을 위한 리샤딩#
샤드 데이터 분포가 특정 샤드 노드에 편향될 경우 해당 데이터를 다른 샤드 노드로 분산 시킬 수 있다.
리샤딩은 파티션 단위로 진행 가능하므로 샤드 테이블이 이미 파티션으로 분할 되어있다면 샤드 매니저를 통해 원하는 파티션을 선택해서 리샤딩이 가능하다.
그렇지 않고, 신규 샤드 노드로 전달해 줄 데이터가 파티션으로 분할되어있지 않은 경우 전체 샤드 노드에 파티션드 테이블 분할 구문을 사용하여 파티션을 분할해 준 후 리샤딩을 진행한다. 다만, 파티션드 테이블을 분할하는 경우 데이터가 이동하는 동안 테이블 락으로 인해서 데이터 양에 따라 서비스가 장시간 중단될 수 있으므로 노드 확장을 고려해서 미리 다수의 파티션으로 분할해 놓을 것을 권장한다.
파티션드 테이블의 분할 구문에 대한 자세한 내용은 SQL Reference를 참고한다.
샤드 노드 추가를 동반한 리샤딩#
노드 추가로 인한 단일 샤드 키 분산 테이블의 리샤딩은 아래와 같이 단계별로 구분해서 작업을 진행한다.
- 노드 추가
- 샤드 관련 객체들 생성 및 설정
- 샤드 테이블 별 리샤딩
먼저 샤드 매니저를 통해 샤드 노드를 추가한 후 리샤딩을 원하는 테이블들을 선정한다. 수동으로도 샤드 노드를 추가하고 샤드 메타를 동기화 할 수 있으나 권장하지 않는다.
리샤딩을 원하는 테이블과 샤드 메타는 기존 샤드 노드와 동일하게 설정한 후 리샤딩을 수행해야하며 샤드 매니저를 통하여 샤드 노드를 추가하는 경우 자동으로 샤드 메타를 복제해 준다. 다만, 샤드 테이블은 생성되어 있지 않으므로 동일한 스키마로 사용자가 생성해야한다.
이 경우에도 파티션 단위로 리샤딩이 가능하므로 샤드 데이터 분포 조정의 설명과 동일하게 수행할 수 있다.
샤드 노드 제거를 동반한 리샤딩#
샤드 노드 제거를 위해서는 제거되는 노드에서 처리중인 데이터를 제거되지 않는 다른 샤드 노드로 옮긴 후 샤드 노드를 제거해야 데이터를 잃어버리지 않는다.
그러므로, 샤드 데이터 분포 조정과 동일하게 데이터를 이동 후 샤드 노드 제거를 진행한다.
노드 제거에서 설명한 것 처럼 노드 제거는 해당 노드가 가지고 있는 샤드 관련 객체를 삭제 후 노드 삭제를 진행한다. 노드 삭제가 모든 샤드 노드에서 적용되고 해당 샤드 메타가 적용되고 응용 프로그램의 연결이 모두 끊기면 노드 제거가 완료된다.
복제 분산 테이블 리샤딩#
복제 분산 테이블의 리샤딩은 신규 샤드 노드 추가를 동반한 경우에만 고려하여 리샤딩을 진행하면 된다. 데이터 분포에 대한 조정 및 샤드 노드 제거와 관련해서는 리샤딩을 고려할 필요가 없다.
신규 샤드 노드를 추가하는 경우 샤드 노드 추가 후 샤드 매니저를 통해 리샤딩을 수행하면 신규 노드에 복제 분산 테이블이 복제되어 서비스가 가능하다.
독립 분산 테이블 리샤딩#
독립 분산 테이블은 테이블 단위로 리샤딩이 가능하며 샤드 노드 추가나 삭제 그리고 데이터 분포 조정을 필요로 할 때 고려해야 한다.
독립 분산 테이블의 리샤딩은 테이블 단위로 진행 된다는 것을 제외하고 단일 키 분산 테이블과 동일하다.