Oracle CDC 2 — Chuẩn bị Oracle cho CDC (Lab)

13 thg 7, 2026 3 lượt xem
#cdc
#oracle
#lab
#archivelog
#supplemental-logging

Oracle CDC 2 — Chuẩn bị Oracle cho CDC (Lab)

Đây là bài LAB thực hành. Bạn sẽ dựng một Oracle Database bằng Docker, bật các tính năng nền tảng bắt buộc cho Change Data Capture (CDC) — ARCHIVELOGsupplemental logging — rồi tạo một user chuyên dụng cho công cụ CDC (Debezium qua LogMiner, hoặc GoldenGate). Cuối bài bạn có một môi trường Oracle sẵn sàng cho các bài tiếp theo về GoldenGate.

Lưu ý quan trọng về sandbox: Các khối lệnh trong bài là Oracle SQL / shell, KHÔNG chạy được trên SQL Builder (sandbox của trang này dùng PostgreSQL). Mỗi khối là một lab step — bạn tự chạy trên container Oracle. Chỗ nào ghi (chạy trên Oracle, không phải SQL Builder) nghĩa là bạn cần thực thi bằng sqlplus trong container, không dán vào SQL Builder.

Cảnh báo an toàn: Toàn bộ cấu hình trong bài là cho lab học tập. Mật khẩu để trần, image XE, db_recovery_file_dest nhỏ, cấp quyền rộng cho user CDC — tất cả KHÔNG được dùng cho production. Production cần image Enterprise/Standard có license, mật khẩu quản lý qua vault, dung lượng FRA (Fast Recovery Area) tính toán kỹ, và quyền cấp theo nguyên tắc tối thiểu.


1. Kiến trúc CDB/PDB và luồng redo → archive

Oracle từ 12c trở đi dùng kiến trúc multitenant: một CDB (Container Database, CDB$ROOT) chứa nhiều PDB (Pluggable Database). Với Oracle XE 19c/21c, PDB mặc định tên là XEPDB1.

Điểm mấu chốt cho CDC:

  • Redo logarchive log thuộc về CDB (mức container root), KHÔNG thuộc từng PDB. Mọi thay đổi dữ liệu ở mọi PDB đều ghi vào cùng một chuỗi redo của CDB.
  • Vì vậy ARCHIVELOG bật ở mức CDB. Còn dữ liệu nghiệp vụ (bảng CUSTOMERS, ACCOUNTS…) và supplemental logging ở mức bảng thì nằm trong PDB.
  • User CDC của Debezium phải là common user (C##...) tạo ở CDB với CONTAINER=ALL, để nó vừa đọc được metadata ở CDB vừa SET CONTAINER xuống PDB.

Luồng: DML trong PDB → sinh redo vào online redo log của CDB → khi log switch, redo được archive vào FRA → công cụ CDC (LogMiner của Debezium, hoặc GoldenGate extract) đọc redo/archive để tái tạo các event thay đổi.


2. Chạy Oracle bằng Docker

Chúng ta dùng image gvenzl/oracle-xe — đây là bản đóng gói cộng đồng phổ biến cho Oracle Database Express Edition (XE), nhẹ và tiện cho lab. Ngoài ra có thể kéo image chính thức từ container-registry.oracle.com (cần đăng nhập tài khoản Oracle SSO và chấp nhận license), nhưng cho lab thì gvenzl/oracle-xe nhanh hơn.

XE là bản gì? Oracle XE miễn phí nhưng bị giới hạn (CPU, RAM, tối đa 12 GB dữ liệu người dùng ở 21c). XE đủ cho lab CDC vì vẫn có redo/archive log, supplemental logging, LogMiner. Production thường dùng Enterprise Edition với license riêng — hành vi có khác biệt nhỏ, khi lên prod hãy kiểm tra tài liệu đúng phiên bản.

Lab step 2.1 — Kéo image và chạy container

# Kéo image XE (chọn tag phiên bản; 21-slim nhẹ, 19.3.0-slim nếu cần 19c)
docker pull gvenzl/oracle-xe:21-slim

# Chạy container
docker run -d \
  --name oracle-cdc \
  -p 1521:1521 \
  -e ORACLE_PASSWORD=OraLab#2026 \
  -v oracle-cdc-data:/opt/oracle/oradata \
  gvenzl/oracle-xe:21-slim

Giải thích tham số:

  • -p 1521:1521 — expose cổng listener Oracle mặc định.
  • -e ORACLE_PASSWORD=... — mật khẩu cho user SYS, SYSTEM (và PDBADMIN). Mật khẩu trên chỉ để lab.
  • -v oracle-cdc-data:/opt/oracle/oradata — persist datafile qua named volume để không mất dữ liệu khi xóa container.
  • CDB mặc định là XE, PDB mặc định là XEPDB1.

Lab step 2.2 — Chờ database sẵn sàng

Lần khởi động đầu tiên image sẽ tạo database, mất vài phút. Theo dõi log:

docker logs -f oracle-cdc

Chờ đến khi thấy dòng DATABASE IS READY TO USE! rồi Ctrl+C để thoát log.


3. Kết nối bằng sqlplus

Ta sẽ vào shell container rồi dùng sqlplus. (Chạy trên Oracle, không phải SQL Builder.)

Lab step 3.1 — Kết nối tới CDB$ROOT

docker exec -it oracle-cdc bash

Trong container:

-- (Oracle) Kết nối vào CDB$ROOT với quyền SYSDBA
sqlplus / as sysdba

Kiểm tra đang đứng ở container nào:

-- (Oracle) Xác nhận đang ở CDB$ROOT
SHOW CON_NAME;
-- Kỳ vọng: CON_NAME = CDB$ROOT

SELECT name, cdb, con_id FROM v$database;
SELECT name, open_mode FROM v$pdbs;

Lab step 3.2 — Kết nối tới PDB XEPDB1

Có hai cách. Trong cùng phiên sqlplus:

-- (Oracle) Chuyển session sang PDB XEPDB1 (cần quyền SYSDBA/SET CONTAINER)
ALTER SESSION SET CONTAINER = XEPDB1;
SHOW CON_NAME;   -- Kỳ vọng: XEPDB1

Hoặc kết nối trực tiếp qua service name (từ ngoài container cũng dùng được nếu có sqlplus/thin client):

# (shell) Kết nối trực tiếp vào PDB qua EZConnect
sqlplus sys/OraLab#2026@//localhost:1521/XEPDB1 as sysdba

Ghi chú: XEPDB1service name của PDB. XE là service của CDB. Nhầm service là lỗi kết nối phổ biến nhất khi mới làm quen multitenant.


4. Bật ARCHIVELOG (mức CDB)

CDC đọc redo/archive log. Ở chế độ NOARCHIVELOG mặc định của XE, redo bị ghi đè sau log switch — LogMiner/GoldenGate không thể đọc lại lịch sử. Do đó bắt buộc bật ARCHIVELOG.

Lab step 4.1 — Kiểm tra trạng thái hiện tại

Kết nối CDB$ROOT as sysdba:

-- (Oracle) Xem log mode hiện tại
SELECT log_mode FROM v$database;   -- thường: NOARCHIVELOG

ARCHIVE LOG LIST;
-- Database log mode: No Archive Mode  (trước khi bật)

Lab step 4.2 — Cấu hình nơi lưu archive (FRA)

Nên đặt archive vào Fast Recovery Area. Với lab, cho dung lượng nhỏ vừa đủ:

-- (Oracle) Cấu hình FRA — chỉ số lab, prod phải tính theo throughput redo
ALTER SYSTEM SET db_recovery_file_dest_size = 10G SCOPE=BOTH;
ALTER SYSTEM SET db_recovery_file_dest = '/opt/oracle/oradata/recovery_area' SCOPE=BOTH;

Cảnh báo: Nếu FRA đầy, database sẽ treo (hang) vì không archive được redo. Trong lab nhớ dọn archive cũ định kỳ (mục 8). Prod dùng RMAN + backup policy để tự dọn.

Lab step 4.3 — Bật ARCHIVELOG

ARCHIVELOG chỉ đổi được khi database ở trạng thái MOUNT (chưa OPEN). Ở multitenant, thao tác này ở CDB, ảnh hưởng toàn bộ PDB.

-- (Oracle) Chuỗi bật ARCHIVELOG — chạy ở CDB$ROOT as sysdba
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
ALTER DATABASE ARCHIVELOG;
ALTER DATABASE OPEN;

Ghi chú multitenant: Khi ALTER DATABASE OPEN ở CDB, các PDB có thể vẫn ở MOUNTED. Mở lại PDB nếu cần:

ALTER PLUGGABLE DATABASE ALL OPEN;

Lab step 4.4 — Xác nhận đã bật

-- (Oracle) Kiểm tra lại
SELECT log_mode FROM v$database;   -- Kỳ vọng: ARCHIVELOG

ARCHIVE LOG LIST;
-- Database log mode: Archive Mode
-- Automatic archival: Enabled

5. Bật supplemental logging

Mặc định Oracle redo log không ghi đủ thông tin để tái tạo một hàng thay đổi từ bên ngoài: nó tối ưu cho recovery, chỉ ghi ROWID + cột thay đổi. CDC cần biết cột nào định danh hàng (key) và đôi khi giá trị đầy đủ của mọi cột. Đó là lý do phải bật supplemental logging.

Ba mức supplemental logging

MứcGhi thêm gìDùng khi
MinimalĐủ để LogMiner nhận diện & nhóm thao tácNền tảng bắt buộc bật trước
Identification key (PK/UK)Cột khóa (PK, hoặc unique nếu không có PK) khi UPDATE/DELETEĐủ cho phần lớn CDC theo khóa
All columnsTẤT CẢ cột (before + after) mỗi lần thay đổiDebezium/GoldenGate cần "before image" đầy đủ

Vì sao Debezium/GoldenGate cần?

  • Debezium (LogMiner): cần ít nhất supplemental log của các cột khóa để định danh hàng; để có đầy đủ before/after (ví dụ capture đúng mọi cột kể cả không đổi), Debezium khuyến nghị bật ALL COLUMNS cho các bảng cần capture.
  • GoldenGate: cũng dựa vào supplemental logging để dựng lại row; GoldenGate có lệnh ADD TRANDATA/ADD SCHEMATRANDATA tự thêm supplemental log cho bảng.

Lab step 5.1 — Bật ở mức database (CDB)

-- (Oracle) Bật minimal supplemental logging ở CDB$ROOT
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;

-- (tùy chọn) Bật all columns ở mức database — tiện lab, nặng cho prod
-- ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

Ghi chú multitenant: Với 19c/21c multitenant, khuyến nghị bật supplemental logging ở CDB$ROOT để phủ toàn bộ. Bật all columns cấp bảng thì làm trong PDB (mục 6). Nếu môi trường của bạn phản hồi khác, kiểm tra tài liệu phiên bản.

Lab step 5.2 — Xác nhận

-- (Oracle) Kiểm tra các cờ supplemental log của database
SELECT supplemental_log_data_min,
       supplemental_log_data_pk,
       supplemental_log_data_ui,
       supplemental_log_data_all
FROM   v$database;
-- SUPPLEMENTAL_LOG_DATA_MIN kỳ vọng: YES (hoặc IMPLICIT)

6. Tạo schema demo + bảng để CDC (trong PDB)

Bây giờ chuyển xuống PDB XEPDB1 để tạo schema nghiệp vụ.

Lab step 6.1 — Tạo user schema và bảng

-- (Oracle) Chạy ở PDB XEPDB1
ALTER SESSION SET CONTAINER = XEPDB1;

-- Tạo schema nghiệp vụ (local user trong PDB)
CREATE USER app_bank IDENTIFIED BY App#Bank2026
  DEFAULT TABLESPACE users
  QUOTA UNLIMITED ON users;
GRANT CREATE SESSION, CREATE TABLE, CREATE SEQUENCE TO app_bank;

-- Bảng CUSTOMERS
CREATE TABLE app_bank.customers (
  customer_id   NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  full_name     VARCHAR2(200) NOT NULL,
  email         VARCHAR2(200),
  created_at    TIMESTAMP DEFAULT SYSTIMESTAMP
);

-- Bảng ACCOUNTS
CREATE TABLE app_bank.accounts (
  account_id    NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  customer_id   NUMBER NOT NULL REFERENCES app_bank.customers(customer_id),
  balance       NUMBER(18,2) DEFAULT 0 NOT NULL,
  status        VARCHAR2(20) DEFAULT 'ACTIVE',
  updated_at    TIMESTAMP DEFAULT SYSTIMESTAMP
);

Lab step 6.2 — Bật supplemental log ALL COLUMNS cho từng bảng

-- (Oracle) Trong PDB XEPDB1 — bật all columns cho các bảng cần capture
ALTER TABLE app_bank.customers ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;
ALTER TABLE app_bank.accounts  ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

Nếu chỉ cần khóa (nhẹ hơn), thay bằng:

ALTER TABLE app_bank.customers ADD SUPPLEMENTAL LOG DATA (PRIMARY KEY) COLUMNS;

Lab step 6.3 — Chèn dữ liệu để sinh redo (kiểm thử về sau)

-- (Oracle) Sinh vài thay đổi để CDC bắt được
INSERT INTO app_bank.customers (full_name, email)
  VALUES ('Nguyen Van A', '[email protected]');
INSERT INTO app_bank.accounts (customer_id, balance)
  VALUES (1, 1000000);
UPDATE app_bank.accounts SET balance = balance + 500000 WHERE account_id = 1;
COMMIT;

7. Tạo user CDC cho Debezium LogMiner

Debezium đọc redo qua LogMiner. Nó cần một common user ở CDB (tên bắt đầu C##) với CONTAINER=ALL, và một loạt quyền để đọc catalog, view V$, và chạy DBMS_LOGMNR. Script dưới đây bám sát tài liệu Debezium Oracle connector.

Cảnh báo: Nhiều quyền ở đây (SELECT ANY TABLE, SELECT ANY TRANSACTION, LOCK ANY TABLE) rất rộng. Chấp nhận được cho lab; production nên siết theo đúng schema cần capture.

Lab step 7.1 — (Tùy chọn) Tạo tablespace riêng cho user CDC

-- (Oracle) Ở CDB$ROOT — tablespace tồn tại ở mọi container để common user dùng
ALTER SESSION SET CONTAINER = CDB$ROOT;
CREATE TABLESPACE logminer_tbs DATAFILE '/opt/oracle/oradata/XE/logminer_tbs01.dbf'
  SIZE 25M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;

ALTER SESSION SET CONTAINER = XEPDB1;
CREATE TABLESPACE logminer_tbs DATAFILE '/opt/oracle/oradata/XE/XEPDB1/logminer_tbs01.dbf'
  SIZE 25M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;

Lab step 7.2 — Tạo common user C##DBZUSER

-- (Oracle) Ở CDB$ROOT as sysdba
ALTER SESSION SET CONTAINER = CDB$ROOT;

CREATE USER c##dbzuser IDENTIFIED BY dbz
  DEFAULT TABLESPACE logminer_tbs
  QUOTA UNLIMITED ON logminer_tbs
  CONTAINER=ALL;

Lab step 7.3 — Cấp quyền (GRANT ... CONTAINER=ALL)

-- (Oracle) Cấp quyền cho user CDC — theo tài liệu Debezium Oracle
GRANT CREATE SESSION            TO c##dbzuser CONTAINER=ALL;
GRANT SET CONTAINER             TO c##dbzuser CONTAINER=ALL;
GRANT SELECT ON V_$DATABASE     TO c##dbzuser CONTAINER=ALL;
GRANT FLASHBACK ANY TABLE       TO c##dbzuser CONTAINER=ALL;
GRANT SELECT ANY TABLE          TO c##dbzuser CONTAINER=ALL;
GRANT SELECT_CATALOG_ROLE       TO c##dbzuser CONTAINER=ALL;
GRANT EXECUTE_CATALOG_ROLE      TO c##dbzuser CONTAINER=ALL;
GRANT SELECT ANY TRANSACTION    TO c##dbzuser CONTAINER=ALL;
GRANT LOGMINING                 TO c##dbzuser CONTAINER=ALL;

GRANT CREATE TABLE              TO c##dbzuser CONTAINER=ALL;
GRANT LOCK ANY TABLE            TO c##dbzuser CONTAINER=ALL;
GRANT CREATE SEQUENCE           TO c##dbzuser CONTAINER=ALL;

GRANT EXECUTE ON DBMS_LOGMNR     TO c##dbzuser CONTAINER=ALL;
GRANT EXECUTE ON DBMS_LOGMNR_D   TO c##dbzuser CONTAINER=ALL;

GRANT SELECT ON V_$LOG           TO c##dbzuser CONTAINER=ALL;
GRANT SELECT ON V_$LOG_HISTORY   TO c##dbzuser CONTAINER=ALL;
GRANT SELECT ON V_$LOGMNR_LOGS   TO c##dbzuser CONTAINER=ALL;
GRANT SELECT ON V_$LOGMNR_CONTENTS       TO c##dbzuser CONTAINER=ALL;
GRANT SELECT ON V_$LOGMNR_PARAMETERS     TO c##dbzuser CONTAINER=ALL;
GRANT SELECT ON V_$LOGFILE               TO c##dbzuser CONTAINER=ALL;
GRANT SELECT ON V_$ARCHIVED_LOG          TO c##dbzuser CONTAINER=ALL;
GRANT SELECT ON V_$ARCHIVE_DEST_STATUS   TO c##dbzuser CONTAINER=ALL;
GRANT SELECT ON V_$TRANSACTION           TO c##dbzuser CONTAINER=ALL;

Ghi chú: Danh sách quyền V$ có thể khác nhẹ giữa các phiên bản/bản vá Debezium. Khi triển khai thật, đối chiếu tài liệu Debezium đúng phiên bản connector bạn dùng.

Lab step 7.4 — Kiểm tra user CDC đăng nhập được

# (shell) Debezium kết nối vào CDB (service XE), rồi tự SET CONTAINER
sqlplus c##dbzuser/dbz@//localhost:1521/XE
-- (Oracle) Trong phiên của c##dbzuser
SELECT count(*) FROM v$database;   -- không lỗi = quyền SELECT V_$DATABASE OK

GoldenGate thay vì Debezium? GoldenGate cấp quyền qua DBMS_GOLDENGATE_AUTH.GRANT_ADMIN_PRIVILEGE('C##GGADMIN', container => 'ALL') và dùng ADD SCHEMATRANDATA để bật supplemental log. Chi tiết ở bài Oracle CDC 3 — Kiến trúc GoldenGate.


8. Kiểm tra tổng thể cấu hình

Chạy loạt truy vấn xác nhận (ở CDB$ROOT as sysdba). (Chạy trên Oracle, không phải SQL Builder.)

Lab step 8.1 — Log mode & supplemental logging

-- (Oracle) Xác nhận toàn bộ điều kiện nền CDC
SELECT log_mode, supplemental_log_data_min, supplemental_log_data_all
FROM   v$database;
-- Kỳ vọng: ARCHIVELOG | YES | (YES nếu bật all ở DB, hoặc NO nếu chỉ bật cấp bảng)

Lab step 8.2 — Redo log & archive log

-- (Oracle) Các nhóm online redo log hiện có
SELECT group#, thread#, bytes/1024/1024 AS mb, status
FROM   v$log
ORDER  BY group#;

-- Ép log switch để sinh một archive rồi kiểm tra
ALTER SYSTEM SWITCH LOGFILE;

-- Danh sách archive log gần nhất
SELECT name, sequence#, first_time, completion_time
FROM   v$archived_log
ORDER  BY sequence# DESC
FETCH FIRST 5 ROWS ONLY;

Lab step 8.3 — Supplemental log cấp bảng (trong PDB)

-- (Oracle) Ở PDB XEPDB1 — kiểm tra bảng nào đã bật ALL COLUMNS
ALTER SESSION SET CONTAINER = XEPDB1;

SELECT owner, table_name, log_group_type, always
FROM   dba_log_groups
WHERE  owner = 'APP_BANK';
-- Kỳ vọng: có dòng cho CUSTOMERS và ACCOUNTS với log_group_type ALL COLUMN LOGGING

Lab step 8.4 — Dọn archive khi FRA đầy (lab)

Trong lab dễ gặp FRA đầy. Dọn bằng RMAN:

# (shell) trong container
rman target /
-- (RMAN) Dọn archive đã cũ (LAB — prod cần backup trước khi xóa!)
DELETE ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-1';

Cảnh báo: Lệnh xóa archive này chỉ dùng cho lab. Ở prod, archive là một phần của chiến lược recovery — xóa không có backup có thể khiến bạn không phục hồi được database.


Tóm tắt

  • Oracle 12c+ dùng kiến trúc CDB/PDB; XE có PDB mặc định XEPDB1. Redo/archive ở mức CDB, dữ liệu nghiệp vụ ở PDB.
  • Dựng lab nhanh bằng docker run gvenzl/oracle-xe; XE đủ cho học CDC nhưng không phải cấu hình production.
  • CDC yêu cầu hai nền tảng: ARCHIVELOG (bật ở CDB qua SHUTDOWN IMMEDIATE → STARTUP MOUNT → ALTER DATABASE ARCHIVELOG → OPEN) và supplemental logging (minimal ở database, ALL COLUMNS cho các bảng cần capture).
  • Debezium cần một common user C##DBZUSER (CONTAINER=ALL) với quyền catalog, view V$, và DBMS_LOGMNR/DBMS_LOGMNR_D.
  • Luôn kiểm tra bằng v$database, v$log, v$archived_log, dba_log_groups.

Tự kiểm tra

  1. Vì sao ARCHIVELOG phải bật ở CDB chứ không phải trong PDB XEPDB1?
  2. Ba mức supplemental logging là gì, và mức nào Debezium khuyến nghị để có đầy đủ before/after image?
  3. Trạng thái database nào bắt buộc để chạy ALTER DATABASE ARCHIVELOG, và chuỗi lệnh để đạt trạng thái đó?
  4. Vì sao user CDC của Debezium phải là common user (C##...) với CONTAINER=ALL?
  5. Nếu db_recovery_file_dest_size đầy thì điều gì xảy ra với database, và trong lab bạn xử lý thế nào?
  6. Truy vấn nào xác nhận một bảng đã bật supplemental log ALL COLUMNS?

Đọc tiếp

Bài viết liên quan

CSV/JSON/Parquet/Avro, lưu trữ theo hàng vs cột, nén, và OLTP vs OLAP.

13 thg 7, 2026 8

Vì sao xử lý phân tán, mô hình Spark (RDD/DataFrame), lazy evaluation, shuffle và tối ưu.

13 thg 7, 2026 5

Data Engineering là gì, vai trò trong vòng đời dữ liệu, và bức tranh hệ sinh thái công cụ.

13 thg 7, 2026 5

Đảm bảo chất lượng & minh bạch dữ liệu bằng dbt: data tests dựng sẵn (unique, not_null, relationships, accepted_values), singular test, unit test, và tài liệu tự sinh kèm lineage graph.

13 thg 7, 2026 5