Oracle CDC 2 — Chuẩn bị Oracle cho CDC (Lab)
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) — ARCHIVELOG và supplemental 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
sqlplustrong 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_destnhỏ, 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 log và archive 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ớiCONTAINER=ALL, để nó vừa đọc được metadata ở CDB vừaSET CONTAINERxuố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 userSYS,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ú:
XEPDB1là service name của PDB.XElà 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ức | Ghi thêm gì | Dùng khi |
|---|---|---|
| Minimal | Đủ để LogMiner nhận diện & nhóm thao tác | Nề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 columns | TẤT CẢ cột (before + after) mỗi lần thay đổi | Debezium/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 SCHEMATRANDATAtự 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ùngADD 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
- Vì sao ARCHIVELOG phải bật ở CDB chứ không phải trong PDB
XEPDB1? - Ba mức supplemental logging là gì, và mức nào Debezium khuyến nghị để có đầy đủ before/after image?
- 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 đó? - Vì sao user CDC của Debezium phải là common user (
C##...) vớiCONTAINER=ALL? - 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? - 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.
Vì sao xử lý phân tán, mô hình Spark (RDD/DataFrame), lazy evaluation, shuffle và tối ưu.
Data Engineering là gì, vai trò trong vòng đời dữ liệu, và bức tranh hệ sinh thái công cụ.
Đả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.