Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Perubahan Tabel Pemantauan di Oracle

Replikasi database tidak lagi terbatas pada konfigurasi Oracle-to-Oracle; Oracle-to-cloud dan Oracle-to-BigQuery hanyalah dua dari berbagai opsi yang sekarang dapat dipilih untuk konfigurasi replikasi. Dalam sejumlah besar konfigurasi ini terletak GoldenGate sebagai alat pilihan, mengingat keserbagunaan dan keandalannya. Sayangnya, ketika mereplikasi Oracle ke platform lain, tindakan seperti modifikasi tabel dapat menimbulkan masalah. Dengan demikian, akan diinginkan untuk melacak perubahan seperti itu untuk mengantisipasi penanganan abends ekstrak GoldenGate dengan anggun dan cepat. Mari kita lihat skenario yang memungkinkan dan tentukan tindakan terbaik.

Pikiran pertama yang mungkin dimiliki DBA adalah Audit Terpadu, karena menyediakan banyak informasi untuk tindakan yang dapat diaudit. Sayangnya 'tabel audit' tidak termasuk dalam daftar hak istimewa yang tersedia untuk diaudit:

SCOTT @ orcl> buat kebijakan audit alter_tab_pol 2 hak istimewa mengubah tabel;hak istimewa mengubah tabel *ERROR pada baris 2:ORA-46355:opsi audit hak istimewa hilang atau tidak valid.SCOTT @ orcl>

Menariknya, hak istimewa 'ALTER ANY TABLE' adalah dapat diaudit, tetapi tidak mengaudit apa yang menurut Anda akan diaudit:

SCOTT @ orcl> buat kebijakan audit table_pol 2 hak istimewa buat tabel apa pun, ubah tabel apa pun, jatuhkan tabel apa pun;Kebijakan audit dibuat.SCOTT @ orcl> audit kebijakan table_pol;Audit berhasil.SCOTT @ orcl> 

Kebijakan tersebut hanya mengaudit pemberian hak istimewa tersebut kepada pengguna lain dan mungkin tidak selalu menghasilkan catatan audit. Persyaratan tersebut belum terpenuhi oleh audit sehingga solusi lain harus dihasilkan. Untungnya, Oracle menawarkan pemicu tingkat sistem yang dapat menghasilkan catatan audit untuk tindakan tersebut. Contoh bagaimana hal ini dapat dilakukan ditunjukkan di bawah ini. Pertama, sebuah tabel dibuat untuk memuat catatan audit yang dihasilkan:

buat tabel ddl_log (operasi varchar2(30),obj_owner varchar2(35),object_name varchar2(35),sql_text varchar2(200),attempt_by varchar2(35),attempt_dt timestamp); buat indeks ddl_log_idx di ddl_log(obj_owner, operation);

Tabel diindeks pada obj_owner dan operasi untuk mempercepat pembuatan laporan. Selanjutnya pemicu dibuat sebagai pengguna yang memiliki tabel yang akan dipantau untuk mencatat semua pernyataan CREATE, ALTER dan DROP yang telah dieksekusi:

buat atau ganti pemicu ddl_triggerbefore membuat atau mengubah atau dropon schemadeclare oper ddl_log.operation%type; sql_text ora_name_list_t; saya pls_integer; mulai saya :=sql_txt(sql_text); jika i =1 maka masukkan ke ddl_log pilih ora_sysevent, ora_dict_obj_owner, ora_dict_obj_name, sql_text(1), user, v_systimestamp dari dual; elsif i =2 lalu masukkan ke ddl_log pilih ora_sysevent, ora_dict_obj_owner, ora_dict_obj_name, sql_text(1)||sql_text(2), user, v_systimestamp dari dual; elsif i>=3 lalu masukkan ke ddl_log pilih ora_sysevent, ora_dict_obj_owner, ora_dict_obj_name, sql_text(1)||sql_text(2)||sql_text(3), user, v_systimestamp dari dual; akhiri if;end ddl_trigger;/

Karena jumlah 64-byte 'potongan' teks SQL bisa sangat besar, pemicu membatasi kolom SQL_TEXT menjadi tiga 'potongan' pertama, membuat panjang maksimum string 192 karakter. Seperti yang diharapkan untuk pernyataan yang lebih besar, teks lengkap tidak akan disediakan tetapi harus mencakup pernyataan 'ubah tabel' secara keseluruhan. Perhatikan bahwa pemicu ini tidak hanya akan menangkap pernyataan ALTER TABLE tetapi juga pernyataan CREATE/ALTER/DROP yang dikirimkan ke database. Ini berarti ubah pengguna, ubah pemicu, ubah paket, ubah fungsi, ubah tablespace, ubah sistem, buat ... dan jatuhkan ... pernyataan juga masuk ke tabel DDL_LOG. Karena itu, tabel dapat tumbuh dengan cepat dan menjadi cukup besar, sehingga rencana untuk menyimpan sejarah yang terbatas harus dibuat. Untuk sebagian besar sistem, 90 hari seharusnya cukup untuk melacak perubahan tabel dalam database. Laporan yang dihasilkan dari data yang dicatat dapat disimpan untuk jangka waktu yang lebih lama (misalnya, 12 bulan) sebelum dihapus.

Contoh skrip untuk mengelola data tabel disediakan di bawah ini; itu memberlakukan jendela data 90 hari. Direktori log dibuat:

mkdir -p /u01/app/Oracle/ddl_chg/purge_logs

Skrip SQL ditulis untuk menghapus catatan lama dari DDL_LOG:

column sys_date new_value dt noprintcolumn name new_value db_nm noprintselect to_char(sysdate,'RRRRMMDD') sys_date dari dual;pilih nama dari v$database;spool /u01/app/Oracle/ddl_chg/purge_logs/ddl_&log_purge_$_log_purge_ logset echo on---- Record dijadwalkan untuk dihapus--select * From ddl_log where effort_dt  

Ini, jelas, tidak dapat dijalankan langsung dari cron (atau penjadwal serupa) sehingga diperlukan skrip pembungkus:

#!/bin/ksh## purge_ddl_log_90.sh## Skrip shell untuk menghapus catatan audit lama# dari tabel DDL_LOG### Temukan database yang dipilih dan atur lingkungan#set -A database `ps -ef | grep [p]mon | grep '' | awk -F"_" '{print $3}'`for i in ${database[@]}## Atur lingkungan untuk database#do ORACLE_SID=$i export ORACLE_SID ORAENV_ASK=NO export ORAENV_ASK unset ORACLE_BASE export ORACLE_BASE PATH=$PATH: . /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## Mulai SQL*Plus dan jalankan skrip /nolog < 

Skrip shell menetapkan lingkungan yang tepat dan ORACLE_SID berdasarkan output dari perintah ps. Skrip perlu diedit untuk memberikan nama database yang akan dicari dan lokasi ORACLE_HOME. Lebih dari satu nama database dapat ditentukan menggunakan | sebagai pemisah:

'abd|def|ghi|jkl'

Ini menyediakan cara untuk membersihkan tabel DDL_LOG di setiap database tempat kombinasi tabel/pemicu ini telah diinstal. Nama database disertakan dalam nama file log untuk menjaga agar jalur pembersihan tetap terpisah untuk setiap database. Lamanya waktu untuk menyimpan file log dapat diubah untuk memenuhi batas penyimpanan sistem yang dipantau.

Laporan perubahan dapat dibuat dari data yang ditemukan di tabel DDL_LOG:

atur ukuran garis 140column sdate new_value sdt noprintselect to_Char(sysdate, 'RRRRMMDDHH24')sdate from dual;column modlen new_value mlen noprintselect 'a'||nvl(max(length(modification)),25) modlen From(pilih obj_owner owner , nama tab object_name, substr(sql_text, instr(sql_text, 'modify ')) modifikasi, effort_dt mod_timefrom ddl_logwhere (instr(sql_text, 'alter table')> 0or instr(sql_text, 'ALTER TABLE')> 0)); kolom objlen new_value olen noprintselect 'a'||nvl(max(length(owner||'.'||tabname)),60) objlen From(pilih pemilik obj_owner, nama tab object_name, substr(sql_text, instr(sql_text, 'modify ') ) modifikasi, effort_dt mod_timefrom ddl_logwhere (instr(sql_text, 'alter table')> 0or instr(sql_text, 'ALTER TABLE')> 0));format modifikasi kolom &mlencolumn format mod_time a29column format nama tab &olenselect owner||'.'|| nama tab nama_tab, modifikasi, mod_timefrom(pilih pemilik obj_owner, nama tab object_name, substr(sql_text, instr(sql_text, 'add ')) modifikasi, upaya_dt mod_timefrom ddl_logwhere instr(lower(sql_text), 'ubah tabel')> 0unionpilih pemilik obj_owner, object_name nama tab, substr(sql_text, instr(sql_text, 'drop ')) modifikasi, upaya_dt mod_timefrom ddl_logwhere instr(lower(sql_text), 'alter table')> 0unionpilih pemilik obj_owner, nama tab object_name, substr(sql_text, instr(sql_text, 'modify ')) modifikasi, try_dt mod_timefrom ddl_logwhere instr(lower(sql_text), 'alter table')> 0unionpilih pemilik obj_owner, nama tab object_name, substr(sql_text, instr(sql_text, 'ADD ')) modifikasi, effort_dt mod_timefrom ddl_log(di mana instr(lower) sql_text), 'ubah tabel')> 0unionpilih pemilik obj_owner, nama tab object_name, substr(sql_text, instr(sql_text, 'DROP ')) modifikasi, upaya_dt mod_timefrom ddl_logwhere instr(lower(sql_text), 'ubah tabel')> 0unionpilih pemilik obj_owner , objek _nama tabname, substr(sql_text, instr(sql_text, 'MODIFY ')) modifikasi, effort_dt mod_timefrom ddl_logwhere instr(lower(sql_text), 'alter table')> 0) dlwhere lower(dl.modification) tidak seperti '%table%' dan mod_time>=trunc(systimestamp)order dengan 1, 3spool /u01/app/Oracle/ddl_chg/log/tab_chg_rpt_&sdt._&1..lst/spool off

Nama database diteruskan ke skrip sehingga akan dimasukkan dalam nama file laporan. Kode hanya melaporkan perubahan tabel (karenanya string panjang kueri UNION) dan menghasilkan laporan yang mirip dengan yang ditunjukkan di bawah ini:

MODIFIKASI TAB_NAME MOD_TIME---------------- ---------------------------- -- -----------------------------SCOTT.DDL_LOG memodifikasi sql_text varchar2(200) 23-NOV-19 01.23.49.859971 PM 

Skrip juga mengatur pemformatan kolom berdasarkan panjang maksimum data yang disimpan untuk mengurangi panjang baris. Data stempel waktu digunakan untuk memberikan nilai tanggal dan waktu yang terlihat untuk catatan perubahan yang dihasilkan. Skrip ini telah diuji tetapi mungkin memerlukan beberapa modifikasi berdasarkan implementasi vendor sistem operasi Linux/Unix.

Bagi DBA yang tidak menjalankan sistem yang direplikasi, ini mungkin tidak banyak berguna. Namun, bagi mereka yang mereplikasi data dari Oracle ke sistem lain (seperti BigQuery, Snowflake, dan sejenisnya), mengetahui kapan perubahan tabel telah terjadi dapat mempermudah penanganan kegagalan replikasi yang disebabkan oleh perubahan tersebut. Semakin cepat proses replikasi dapat kembali ke jalurnya, semakin cepat sistem yang mengandalkan data yang direplikasi tersebut dapat kembali berfungsi.

# # #

Lihat artikel oleh David Fitzjarrell


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. ORA-16789:log redo siaga tidak dikonfigurasi dengan benar

  2. CURRENT_TIMESTAMP() Fungsi di Oracle

  3. Hibernasi kueri asli - kolom char(3)

  4. Permintaan Oracle untuk menemukan semua kemunculan karakter dalam sebuah string

  5. Membuat tabel dari kueri menggunakan tablespace yang berbeda (Oracle SQL)