Batch Execution은 RDBMS 상에서 우리가 사용하는 Batch 관련 API라고 이해하는 것이 용이하다. DML 각각을 모두 쿼리 형태로 변환하여 전달하기보단, 같은 형태의 쿼리라면 데이터를 Batch단위로 모아서 서버에서 사용하도록 하는 기능이다.
이 기능을 사용하면 Insert 와 같은 DML이 연속해서 들어올 때, Target Database 의 성능을 향상 시킬 수 있다. 이를 통해 데이터 처리 속도를 증가 시키고 동기화 속도를 끌어올려줄 수 있다.
하지만 제약사항도 존재하는 기능으로, 아래와 같은 두 가지 관점에서 고려할 수 있다.
같은 형태의 쿼리
Batch로 모았을 때의 한계
ProSync는 한 트랜잭션에서 DML이 연속해서 들어올 때 이 순서를 임의대로 바꾸지 않는다. 입력되는 모든 쿼리를 순서대로 적용해야 정합성이 깨지지 않는다는 대전제 때문에 이와 같이 처리가 된다.
문제는 이렇게 되면 Insert * 3, Update*3, Delete* 3의 순서로 데이터가 들어올 때와 (Insert, Update, Delete) * 3의 순서로 데이터가 들어올 때 Batch Execution 입장에서 큰 차이가 발생한다.
유사한 쿼리가 연속해서 들어온다면 ProSync는 이를 Batch로 묶어서 처리를 할 수가 있지만, 쿼리들의 형태가 연속적이지 않게 들어온다면 Batch로 처리할 수가 없다. 따라서 두 트랜잭션의 결과가 동일하더라도 하나는 Batch 처리가 가능하고 다른 하나는 Batch 처리가 불가능하다.
트랜잭션 내에 같은 형태의 쿼리들이 연속해서 들어온다고 가정을 하여도 성능 향상이 미미한 경우도 존재한다. 예를 들어 Insert의 경우 Batch 동작을 통해 데이터의 개수나 크기 등을 Target Database에 미리 알려준다면 Database는 이에 맞는 플랜을 세워서 최적화 하여 처리가 가능하다. 하지만 Delete나 Update 처럼 각 row 별로 Where Clause에 의해 따로 탐색을 해야 하는 형태로 들어온다면 아무리 모아 보내도 서버 입장에선 하나씩 처리하나, 모아서 들어온걸 하나씩 처리하나 큰 차이가 없다고 볼 수 있다.
따라서 ProSync는 특별한 설정이 없다면 Insert에 대한 Batch만 처리하는 것이 기본 동작이다. 하지만 Database 별로 처리하는 방식이 달라질 수 있기 때문에 Batch 사용 여부는 파라미터로 모두 관리가 된다.
Parameter 별 제공하는 기능이다.
USE_BATCH_MODE
기본 값은 Y 로, Batch는 항상 동작하도록 되어 있다.
BATCH_MEM_SIZE
기본 값은 10MB로 서버에 보낼 때 최대 10MB의 데이터까지만 쌓고 쿼리에 대한 처리를 요청한다.
USE_ONLY_INSERT_BATCH
Insert 만 Batch 로 처리할 것 인지에 대한 파라미터로 기본 값은 Y 이다.
커밋이 요청된 트랜잭션은 반영을 할 수 있으면 반영을 하고, 반영을 할 수 없으면 큐에서 대기하게 된다. 반영 가능 여부는 반영하고자 하는 트랜잭션과 반영 중인 트랜잭션 간의 의존성 체크를 통해 서로 독립적일 경우 반영이 가능하다고 판단한다.
의존성 체크는 Table과 Row 단위 모두 확인을 한다. 트랜잭션은 레코드로 이루어져 있고, 레코드에는 레코드가 접근하는 Row가 정해져 있기 때문에, 해당 데이터를 기반으로 다른 트랜잭션과 의존 관계인지 여부를 판단한다.
의존성 확인 동작은 RedBlack Tree(RBT)와 Linked List로 관리가 되고 있다. Table 단위로 RBT를 확인하고, Table이 확인되면, 해당 Table 노드 내의 RBT에서 Row를 확인한다. 이 위치엔 Linked List가 존재하며, 트랜잭션은 해당 List에 의존성 객체(TX Dependency)를 달아 놓는다.
이 동작을 통해 트랜잭션이 접근하는 모든 Row에 대한 Linked List에 TX Dependency가 등록이 된다. 반영 중인 트랜잭션이나 반영 대기 중인 트랜잭션 모두 이 구조 안에서 관리된다.
반영 가능 여부는 트랜잭션의 모든 TX Dependency가 Linked List의 front에 존재하는지의 여부로 확인한다. 하나라도 front에 존재하지 않는다면 반영이 불가능하고, 앞서 반영 중인 트랜잭션의 완료를 대기하게 된다.
반영이 가능한 경우는 위 그림과 같이 모든 의존성 체크를 했을 때 Linked List 상에 TX Dependency 가 가장 앞선 경우이다.
만약 위 그림과 같이 xid: 111인 트랜잭션이 아직 반영이 끝나지 않았다면 대기하게 된다. 반영이 완료된 트랜잭션은 위 Linked list에서 제거가 되고, xid: 112가 반영 가능하게 되면 반영 작업을 진행한다.
관련 파라미터는 REPLAY_THREAD_CNT 로, 해당 값이 올라가면 병렬 세션의 수가 많아진다. 하지만 위 로직에서 알 수 있듯이 결국 RBT 내에서 Table, Row단위로 TX Dependency가 잘 풀려야 병렬 반영이 가능하다. 이로 인해 숫자를 올린다고 반드시 올린 숫자만큼 정비례하게 증가하지 못하는 경우도 발생한다.
Redo Log는 물리적인 위치에 대한 변경분이 남는다. RDBMS (주로 Oracle, Tibero) 에서는 row 데이터가 ROWID 라는 고유의 값을 가지게 되는데, 이 ID에는 데이터 파일의 위치, 파일 내 데이터 블록의 위치, 블록 내 row의 위치 에 대한 정보가 저장되어 있다.
ProSync는 이 물리적으로 정해진 ROWID만 가지고는 Target Database에서 정확하게 어떤 row인지 판별할 수가 없다. 왜냐하면 데이터 파일도 다를 것이고, 블록 위치나 row 위치 정보도 모두 다르기 때문에 ROWID로는 서로 다른 Database의 row를 매칭 시키기가 어렵다.
따라서 SUPPLEMENTAL_LOGGING옵션 등을 통해 row 데이터의 추가적인 정보를 Redo Log상에 함께 남기게 된다. 예를 들면, 사용자가 Where Clause에 1개의 Column정보만 넣었다고 하더라도, Redo Log에는 해당 Row 내에 있는 모든 Column 정보가 다 남도록 해준다.
Target Database와 Apply 프로세스는 이 정보를 가지고 쿼리를 재구축한다. 다만 이렇게 되면, Primary key 를 가지고 있는 테이블 입장에선 불필요한 다른 컬럼 정보들을 Where Clause에 입력해주는 경우가 생긴다. Database의 플랜 별로 최적화되어 잘 처리될 수도 있지만, 불필요한 상황 자체를 방어하기 위해 ProSync에선 Primary key만 사용할지에 대한 여부를 파라미터로 관리한다.
USE_PK_FOR_WHERE
이 파라미터를 사용하면 Primary key가 있는 테이블에 대한 Update나 Delete 시에 Where Clause에는 Primary key만 입력하게 된다.

ProSync는 Apply 프로세스 지연 시 모든 곳에 지연이 발생하게 된다. 이 때문에 성능을 올릴 수 있는 수단들이 존재한다. 본 장에서는 Performance 측면에서 설정할 수 있는 Configuration들에 대해 알아본다.
