Việc sao chép cơ sở dữ liệu không còn bị giới hạn đối với các cấu hình Oracle-to-Oracle; Oracle-to-cloud và Oracle-to-BigQuery chỉ là hai trong số các tùy chọn khác nhau hiện có thể được chọn cho các cấu hình sao chép. Trong số rất nhiều cấu hình này, GoldenGate là công cụ được lựa chọn, do tính linh hoạt và độ tin cậy của nó. Thật không may, khi sao chép Oracle sang một nền tảng khác, các hành động chẳng hạn như sửa đổi bảng có thể ném một cái cờ lê vào công việc. Do đó, chúng tôi mong muốn theo dõi những thay đổi như vậy để dự đoán việc xử lý trích xuất GoldenGate diễn ra một cách duyên dáng và nhanh chóng. Hãy xem xét các tình huống có thể xảy ra và xác định hướng hành động tốt nhất.
Ý tưởng đầu tiên mà DBA có thể có là Kiểm toán thống nhất, vì nó cung cấp nhiều thông tin cho các hành động có thể kiểm toán. Than ôi "bảng kiểm tra" không nằm trong danh sách các đặc quyền có sẵn để kiểm tra:
SCOTT @ orcl > create audit policy alter_tab_pol 2 privileges alter table; privileges alter table * ERROR at line 2: ORA-46355: missing or invalid privilege audit option. SCOTT @ orcl >
Điều thú vị là đặc quyền ‘ALTER ANY TABLE’ is có thể kiểm tra, nhưng nó không kiểm tra những gì bạn có thể nghĩ rằng sẽ được kiểm toán:
SCOTT @ orcl > create audit policy table_pol 2 privileges create any table, alter any table, drop any table; Audit policy created. SCOTT @ orcl > audit policy table_pol; Audit succeeded. SCOTT @ orcl >
Chính sách như vậy chỉ kiểm tra việc cấp các đặc quyền đó cho người dùng khác và không phải lúc nào cũng có thể tạo ra hồ sơ kiểm tra. Yêu cầu này vẫn chưa được thực hiện bởi kiểm toán vì vậy một giải pháp khác phải được đưa ra. May mắn thay, Oracle cung cấp các trình kích hoạt cấp hệ thống có thể tạo ra các bản ghi kiểm tra cho các hành động như vậy. Dưới đây là một ví dụ về cách thực hiện điều này. Đầu tiên, một bảng được tạo để chứa các bản ghi kiểm tra được tạo:
create table ddl_log ( operation varchar2(30), obj_owner varchar2(35), object_name varchar2(35), sql_text varchar2(200), attempt_by varchar2(35), attempt_dt timestamp); create index ddl_log_idx on ddl_log(obj_owner, operation);
Bảng được lập chỉ mục trên obj_owner và hoạt động để tăng tốc độ tạo báo cáo. Tiếp theo, một trình kích hoạt được tạo với tư cách là người dùng sở hữu các bảng được theo dõi để ghi lại tất cả các câu lệnh CREATE, ALTER và DROP đã được thực thi:
create or replace trigger ddl_trigger before create or alter or drop on schema declare oper ddl_log.operation%type; sql_text ora_name_list_t; i pls_integer; begin i := sql_txt(sql_text); if i = 1 then insert into ddl_log select ora_sysevent, ora_dict_obj_owner, ora_dict_obj_name, sql_text(1), user, v_systimestamp from dual; elsif i = 2 then insert into ddl_log select ora_sysevent, ora_dict_obj_owner, ora_dict_obj_name, sql_text(1)||sql_text(2), user, v_systimestamp from dual; elsif i >= 3 then insert into ddl_log select ora_sysevent, ora_dict_obj_owner, ora_dict_obj_name, sql_text(1)||sql_text(2)||sql_text(3), user, v_systimestamp from dual; end if; end ddl_trigger; /
Vì số lượng ‘phần’ 64 byte của văn bản SQL có thể khá lớn, trình kích hoạt giới hạn cột SQL_TEXT ở ba ‘phần’ đầu tiên, làm cho độ dài tối đa của chuỗi là 192 ký tự. Như mong đợi đối với các câu lệnh lớn hơn, văn bản hoàn chỉnh sẽ không được cung cấp nhưng nó sẽ ghi lại toàn bộ bất kỳ câu lệnh ‘bảng thay đổi’ nào. Lưu ý rằng trình kích hoạt này sẽ nắm bắt không chỉ các câu lệnh ALTER TABLE mà còn bất kỳ câu lệnh CREATE / ALTER / DROP nào được gửi đến cơ sở dữ liệu. Điều này có nghĩa là các câu lệnh thay đổi người dùng, thay đổi trình kích hoạt, thay đổi gói, thay đổi chức năng, thay đổi không gian bảng, thay đổi hệ thống, tạo… và thả… cũng được ghi vào bảng DDL_LOG. Bởi vì điều này, bảng có thể phát triển nhanh chóng và trở nên khá lớn, do đó, một kế hoạch để lưu giữ một lịch sử hữu hạn nên được tạo ra. Đối với hầu hết các hệ thống, 90 ngày là đủ để theo dõi các thay đổi của bảng trong cơ sở dữ liệu. Các báo cáo được tạo từ dữ liệu đã ghi có thể được lưu giữ trong thời gian dài hơn (ví dụ:12 tháng) trước khi bị xóa.
Tập lệnh mẫu để quản lý dữ liệu bảng được cung cấp bên dưới; nó thực thi thời hạn 90 ngày dữ liệu. Thư mục nhật ký được tạo:
mkdir -p /u01/app/oracle/ddl_chg/purge_logs
Tập lệnh SQL được viết để xóa các bản ghi cũ khỏi DDL_LOG:
column sys_date new_value dt noprint column name new_value db_nm noprint select to_char(sysdate,'RRRRMMDD') sys_date from dual; select name from v$database; spool /u01/app/oracle/ddl_chg/purge_logs/ddl_log_purge_$db_nm._&dt..log set echo on -- -- Records slated for removal -- select * From ddl_log where attempt_dt < sysdate - 90; -- -- Delete selected records -- delete from ddl_log where attempt_dt < sysdate - 90; commit; spool off set echo off
Điều này, rõ ràng, không thể chạy trực tiếp từ cron (hoặc bất kỳ bộ lập lịch tương tự nào) vì vậy cần có một tập lệnh trình bao bọc:
#!/bin/ksh # # purge_ddl_log_90.sh # # Shell script to purge old audit records # from the DDL_LOG table # # # Find the selected database and set the environment # set -A database `ps -ef | grep [p]mon | grep '<name>' | awk -F"_" '{print $3}'` for i in ${database[@]} # # Set the environment for the database # do ORACLE_SID=$i export ORACLE_SID ORAENV_ASK=NO export ORAENV_ASK unset ORACLE_BASE export ORACLE_BASE PATH=$PATH:<ORACLE_HOME/bin location> . <ORACLE_HOME/bin>/oraenv -s LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib:$ORACLE_HOME/precomp/public export LD_LIBRARY_PATH PATH=$ORACLE_HOME/bin:$PATH export PATH # # Start SQL*Plus and execute the script # sqlplus /nolog <<EOF connect / as sysdba @/u01/app/oracle/ddl_chg/purge_ddl_log_90.sql EOF done # # Make the output files readable for all * cd /u01/app/oracle/ddl_chg/purge_logs chmod 666 *.log # # Remove old purge logs # find . -name "purge*log" -mtime +365 -exec /bin/rm -rf {} ;
Tập lệnh shell đặt môi trường thích hợp và ORACLE_SID dựa trên đầu ra của lệnh ps. Tập lệnh sẽ cần được chỉnh sửa để cung cấp tên cơ sở dữ liệu cần tìm và vị trí ORACLE_HOME. Có thể chỉ định nhiều hơn một tên cơ sở dữ liệu bằng cách sử dụng | như một dấu phân cách:
'abd|def|ghi|jkl'
Điều này cung cấp một cách để xóa bảng DDL_LOG trong mọi cơ sở dữ liệu nơi kết hợp bảng / trình kích hoạt này đã được cài đặt. Tên cơ sở dữ liệu được bao gồm trong tên tệp nhật ký để giữ các đường mòn thanh lọc riêng biệt cho từng cơ sở dữ liệu. Khoảng thời gian lưu giữ các tệp nhật ký có thể được thay đổi để đáp ứng giới hạn lưu trữ của hệ thống đang được giám sát.
Báo cáo thay đổi có thể được tạo từ dữ liệu được tìm thấy trong bảng DDL_LOG:
set linesize 140 column sdate new_value sdt noprint select to_Char(sysdate, 'RRRRMMDDHH24')sdate from dual; column modlen new_value mlen noprint select 'a'||nvl(max(length(modification)),25) modlen From (select obj_owner owner, object_name tabname, substr(sql_text, instr(sql_text, 'modify ')) modification, attempt_dt mod_time from ddl_log where (instr(sql_text, 'alter table') > 0 or instr(sql_text, 'ALTER TABLE') > 0)); column objlen new_value olen noprint select 'a'||nvl(max(length(owner||'.'||tabname)),60) objlen From (select obj_owner owner, object_name tabname, substr(sql_text, instr(sql_text, 'modify ')) modification, attempt_dt mod_time from ddl_log where (instr(sql_text, 'alter table') > 0 or instr(sql_text, 'ALTER TABLE') > 0)); column modification format &mlen column mod_time format a29 column tab_name format &olen select owner||'.'|| tabname tab_name, modification, mod_time from (select obj_owner owner, object_name tabname, substr(sql_text, instr(sql_text, 'add ')) modification, attempt_dt mod_time from ddl_log where instr(lower(sql_text), 'alter table') > 0 union select obj_owner owner, object_name tabname, substr(sql_text, instr(sql_text, 'drop ')) modification, attempt_dt mod_time from ddl_log where instr(lower(sql_text), 'alter table') > 0 union select obj_owner owner, object_name tabname, substr(sql_text, instr(sql_text, 'modify ')) modification, attempt_dt mod_time from ddl_log where instr(lower(sql_text), 'alter table') > 0 union select obj_owner owner, object_name tabname, substr(sql_text, instr(sql_text, 'ADD ')) modification, attempt_dt mod_time from ddl_log where instr(lower(sql_text), 'alter table') > 0 union select obj_owner owner, object_name tabname, substr(sql_text, instr(sql_text, 'DROP ')) modification, attempt_dt mod_time from ddl_log where instr(lower(sql_text), 'alter table') > 0 union select obj_owner owner, object_name tabname, substr(sql_text, instr(sql_text, 'MODIFY ')) modification, attempt_dt mod_time from ddl_log where instr(lower(sql_text), 'alter table') > 0) dl where lower(dl.modification) not like '%table%' and mod_time >= trunc(systimestamp) order by 1, 3 spool /u01/app/oracle/ddl_chg/log/tab_chg_rpt_&sdt._&1..lst / spool off
Tên cơ sở dữ liệu được chuyển cho tập lệnh vì vậy nó sẽ được bao gồm trong tên tệp báo cáo. Mã chỉ báo cáo về các thay đổi của bảng (do đó là chuỗi dài các truy vấn UNION) và tạo ra một báo cáo tương tự như báo cáo được hiển thị bên dưới:
TAB_NAME MODIFICATION MOD_TIME ---------------- ------------------------------ ----------------------------- SCOTT.DDL_LOG modify sql_text varchar2(200) 23-NOV-19 01.23.49.859971 PM
Tập lệnh cũng đặt định dạng cột dựa trên độ dài tối đa của dữ liệu được lưu trữ để có thể giảm độ dài dòng. Dữ liệu dấu thời gian đã được sử dụng để cung cấp cả giá trị ngày tháng và thời gian hiển thị cho các bản ghi thay đổi đã tạo. Các tập lệnh này đã được thử nghiệm nhưng có thể yêu cầu một số sửa đổi dựa trên việc triển khai Linux / Unix của nhà cung cấp hệ điều hành.
Đối với những DBA không chạy hệ thống sao chép, điều này có thể không được sử dụng nhiều. Tuy nhiên, đối với những dữ liệu sao chép từ Oracle sang các hệ thống khác (chẳng hạn như BigQuery, Snowflake và các hệ thống tương tự), việc biết khi nào các thay đổi bảng xảy ra có thể giúp dễ dàng xử lý các lỗi sao chép do những thay đổi đó tạo ra. Quá trình sao chép có thể trở lại đúng hướng càng nhanh thì các hệ thống dựa vào dữ liệu được sao chép đó có thể trở lại chức năng càng nhanh.
# # #
Xem các bài viết của David Fitzjarrell