diff --git a/Golden_Gate/example_02/setup_extract_pump_replicat_02.md b/Golden_Gate/example_02/setup_extract_pump_replicat_02.md new file mode 100644 index 0000000..af6831d --- /dev/null +++ b/Golden_Gate/example_02/setup_extract_pump_replicat_02.md @@ -0,0 +1,285 @@ +On source database: + +```sql +create table R2D2.T1 (i1 INTEGER, i2 INTEGER, n1 NUMBER, d1 DATE, c1 varchar2(30)); +alter table R2D2.T1 add constraint T1PK primary key(i1); +``` + +```sql +SET SERVEROUTPUT ON; + +DECLARE + l_total_rows CONSTANT PLS_INTEGER := 10000000; + l_batch_size CONSTANT PLS_INTEGER := 10000; + + l_iterations PLS_INTEGER; + l_remaining_rows PLS_INTEGER; +BEGIN + -- Calculate how many full batches and if there's a remainder + l_iterations := TRUNC(l_total_rows / l_batch_size); + l_remaining_rows := MOD(l_total_rows, l_batch_size); + + DBMS_OUTPUT.PUT_LINE('Starting insert of ' || l_total_rows || ' rows...'); + + -- 1. Process full batches + FOR i IN 1 .. l_iterations LOOP + INSERT /*+ APPEND */ INTO R2D2.T1 (i1, i2, n1, d1, c1) + SELECT + ((i - 1) * l_batch_size) + level, + ((i - 1) * l_batch_size) + level + 1000000, + round(dbms_random.value(1, 100)), + SYSDATE - dbms_random.value(0, 365), + dbms_random.string('x', 20) + FROM dual + CONNECT BY level <= l_batch_size; + + COMMIT; + DBMS_OUTPUT.PUT_LINE('Batch ' || i || ' committed (' || (i * l_batch_size) || ' rows total).'); + END LOOP; + + -- 2. Process the remaining rows (if total_rows is not perfectly divisible by batch_size) + IF l_remaining_rows > 0 THEN + INSERT /*+ APPEND */ INTO R2D2.T1 (i1, i2, n1, d1, c1) + SELECT + (l_iterations * l_batch_size) + level, + (l_iterations * l_batch_size) + level + 1000000, + round(dbms_random.value(1, 100)), + SYSDATE - dbms_random.value(0, 365), + dbms_random.string('x', 20) + FROM dual + CONNECT BY level <= l_remaining_rows; + + COMMIT; + DBMS_OUTPUT.PUT_LINE('Final batch committed. Total rows: ' || l_total_rows); + END IF; + +EXCEPTION + WHEN OTHERS THEN + ROLLBACK; + DBMS_OUTPUT.PUT_LINE('Error encountered: ' || SQLERRM); + RAISE; +END; +/ +``` + +On target database: +```sql +create table C3PO.T1 (i1 INTEGER, i2 INTEGER, n1 NUMBER, d1 DATE, c1 varchar2(30)); +alter table C3PO.T1 add constraint T1PK primary key(i1); +``` + + +On target Golden Gate deployement create extract: + +``` +dblogin useridalias EREP +list tables R2D2.* +add trandata R2D2.T1 +-- delete trandata R2D2.T1 +edit params EXTRAA +``` + +Define extract paramfile: +``` +extract EXTRAA +useridalias NABOOPRD +sourcecatalog EREP +exttrail ./dirdat/aa +purgeoldextracts +checkpointsecs 1 +ddl include mapped +warnlongtrans 1h, checkinterval 30m +------------------------------------ +table R2D2.T1; +``` + +Add, register and start extract: + +``` +dblogin useridalias NABOOPRD +add extract EXTRAA, integrated tranlog, begin now +add exttrail ./dirdat/aa, extract EXTRAA +register extract EXTRAA, database container (EREP) +start extract EXTRAA +info extract EXTRAA detail +``` + +For PUMP process I did all from OGG GUI: +- on SOURCE and TARGET site, define an OPERATOR user in the **deployement**, NOT in Sevice Manager +- on SOURCE site define a PATH CONECTION alias using the previousely defined OPERATOR user +- on source site create the distribution PATH authentification type `wss` authentification type `OGG`, target receiver service (good host and port), user alias from PATH CONECTION + + +On target Golden Gate deployement, if not already done: +``` +edit GLOBALS +``` + +and put: +``` +ggschema c##oggadmin +checkpointtable c##oggadmin.checkpt +``` + +Replicat creation: +``` +edit params REPLAA +``` + +Define replicat paramfile: +``` +replicat REPLAA +useridalias GERISS +dboptions enable_instantiation_filtering +discardfile REPLAA.dsc, purge, megabytes 10 + +map EREP.R2D2.T1, target GERISS.C3PO.T1; +``` + +``` +dblogin useridalias GENOSISPRD +add checkpointtable GERISS.c##oggadmin.checkpt +add replicat REPLAA, integrated, exttrail ./dirdat/aa +start replicat REPLAA +info replicat REPLAA +``` + +```sql +SET SERVEROUTPUT ON; +SET FEEDBACK OFF; + +DECLARE + -- 1. Configuration Constants + l_start_val CONSTANT PLS_INTEGER := &starting_value; -- Start for i1 and i2 + l_sleep_seconds CONSTANT PLS_INTEGER := 30; -- Pause between cycles + l_total_cycles CONSTANT PLS_INTEGER := &number_of_cycles; -- How many times to run + + -- Internal trackers + l_current_id PLS_INTEGER := l_start_val; + l_random_pk PLS_INTEGER; + + -- Collection to hold random PKs for delete/update + type t_ids is table of R2D2.T1.i1%type; + l_id_list t_ids; +BEGIN + DBMS_OUTPUT.PUT_LINE('Starting simulation at ID: ' || l_current_id); + + FOR cycle IN 1 .. l_total_cycles LOOP + + -- TASK 1: Insert 10 new lines + INSERT INTO R2D2.T1 (i1, i2, n1, d1, c1) + SELECT + l_current_id + level, + l_current_id + level, -- Ensuring i2 is unique by mirroring i1 + round(dbms_random.value(1, 100)), + SYSDATE - dbms_random.value(0, 365), + dbms_random.string('x', 20) + FROM dual + CONNECT BY level <= 10; + + l_current_id := l_current_id + 10; + + -- TASK 2: Delete 5 random lines + -- We sample the table to find 5 existing IDs + DELETE FROM R2D2.T1 + WHERE i1 IN ( + SELECT i1 FROM ( + SELECT i1 FROM R2D2.T1 ORDER BY dbms_random.value + ) WHERE rownum <= 5 + ); + + -- TASK 3: Update 2 random lines + -- We pick 2 IDs and change their random data + UPDATE R2D2.T1 + SET n1 = round(dbms_random.value(1, 100)), + d1 = SYSDATE - dbms_random.value(0, 365), + c1 = dbms_random.string('x', 20) + WHERE i1 IN ( + SELECT i1 FROM ( + SELECT i1 FROM R2D2.T1 ORDER BY dbms_random.value + ) WHERE rownum <= 2 + ); + + COMMIT; + + DBMS_OUTPUT.PUT_LINE('Cycle ' || cycle || ' complete. Last ID: ' || (l_current_id - 1)); + + -- Pause before next iteration + IF cycle < l_total_cycles THEN + DBMS_SESSION.SLEEP(l_sleep_seconds); + END IF; + + END LOOP; + + DBMS_OUTPUT.PUT_LINE('Simulation finished.'); +EXCEPTION + WHEN OTHERS THEN + ROLLBACK; + DBMS_OUTPUT.PUT_LINE('Error: ' || SQLERRM); +END; +/ +``` + + + + +## Interesting things + +Deleting all 9999998 from source: +``` +SQL> select max(i1),max(i2) from R2D2.T1@EREP; + + MAX(I1) MAX(I2) +---------- ---------- + 9999998 10999998 + +SQL> delete from R2D2.T1@EREP; + +9999998 rows deleted. + +SQL> commit; + +Commit complete. + +SQL> select max(i1),max(i2) from R2D2.T1@EREP; + + MAX(I1) MAX(I2) +---------- ---------- + +``` + +generated 706 execution of `DELETE /*+ restrict_all_ref_cons */ FROM "C3PO"."T1" WHERE "I1"=:1` + +``` +SQL> @sqlid 6hhfc9ydtaq64 % +Show SQL text, child cursors and execution stats for SQLID 6hhfc9ydtaq64 child % + + INST_ID HASH_VALUE PLAN_HASH_VALUE CH# SQL_TEXT +---------- ---------- --------------- ----- ------------------------------------------------------------------------------------------------------------------------------------------------------ + 1 2610256068 1520089403 0 DELETE /*+ restrict_all_ref_cons */ FROM "C3PO"."T1" WHERE "I1"=:1 + + + INST_ID CH# PLAN_HASH PARSES H_PARSES EXECUTIONS FETCHES ROWS_PROCESSED ROWS_PER_FETCH CPU_SEC_EXEC ELA_SEC_EXEC LIOS_PER_EXEC PIOS_PER_EXEC TOTAL_CPU_SEC TOTAL_ELA_SEC TOTAL_IOWAIT_SEC TOTAL_LIOS TOTAL_PIOS SORTS USERS_EXECUTING LAST_ACTIVE_TIME PARENT_HANDLE OBJECT_HANDLE +---------- ----- ---------- ---------- ---------- ---------- ---------- -------------- -------------- ------------ ------------ ------------- ------------- ------------- ------------- ---------------- ---------- ---------- ---------- --------------- ------------------- ---------------- ---------------- + 1 0 1520089403 2 1 706 0 9999999 .134 .324 72541 21 94.609 228.586 4.078476 51214058 14969 0 0 2026-05-09 18:04:17 0000000072EA74E8 00000000653A98A0 + +``` + +I guess Golden Gate sent 706 bulk delete. + + +Re-inserting 10000000 lines in source table, create 1040 bulk insert target side: + + INST_ID HASH_VALUE PLAN_HASH_VALUE CH# SQL_TEXT +---------- ---------- --------------- ----- ------------------------------------------------------------------------------------------------------------------------------------------------------ + 1 2973785138 0 0 INSERT /*+ restrict_all_ref_cons */ INTO "C3PO"."T1" ("I1","I2","N1","D1","C1") VALUES (:1 ,:2 ,:3 ,:4 ,:5 ) + + + INST_ID CH# PLAN_HASH PARSES H_PARSES EXECUTIONS FETCHES ROWS_PROCESSED ROWS_PER_FETCH CPU_SEC_EXEC ELA_SEC_EXEC LIOS_PER_EXEC PIOS_PER_EXEC TOTAL_CPU_SEC TOTAL_ELA_SEC TOTAL_IOWAIT_SEC TOTAL_LIOS TOTAL_PIOS SORTS USERS_EXECUTING LAST_ACTIVE_TIME PARENT_HANDLE OBJECT_HANDLE +---------- ----- ---------- ---------- ---------- ---------- ---------- -------------- -------------- ------------ ------------ ------------- ------------- ------------- ------------- ---------------- ---------- ---------- ---------- --------------- ------------------- ---------------- ---------------- + 1 0 0 7 1 1040 0 10000000 .029 .127 1681 0 30.092 131.704 .290696 1748314 264 0 0 2026-05-10 15:41:57 0000000062D19340 00000000655E91F8 + + + + + diff --git a/Golden_Gate/setup.md b/Golden_Gate/setup.md index 0d9113d..b87d59b 100644 --- a/Golden_Gate/setup.md +++ b/Golden_Gate/setup.md @@ -20,6 +20,7 @@ grant create session, connect,resource,alter system, select any dictionary, flas exec dbms_goldengate_auth.grant_admin_privilege(grantee => 'c##oggadmin',container=>'all'); alter user c##oggadmin set container_data=all container=current; grant alter any table to c##oggadmin container=ALL; +grant create procedure,create view to c##oggadmin container=all; alter system set enable_goldengate_replication=true scope=both; alter database force logging; alter database add supplemental log data; @@ -151,6 +152,12 @@ If `GERISS` PDB will be a replication target, create the checkpoint table: dblogin useridalias GENOSISPRD add checkpointtable GERISS.c##oggadmin.checkpt +For replicat add **heartbeattable** in the **PDB**: + + dblogin useridalias GERISS + add heartbeattable + + Set **global** parameters: edit GLOBALS