Toad for Oracle – Zaboravljeni pasvordi…

Sunday, 13.10.2013 – mradovan

Lijepo je imati uključenu opciju “Save password” u našim alatima, pa ne moramo zamarati svoje male sive ćelije pamćenjem istih. Ponekad zaboravimo što smo si upisali za password, a iako postoje i raznorazni password manager programi, ljenost je ta koja je ponekad jača od alata :)

Postoji više solucija za pronalaženje istih, dat ću samo linkove na dva rješenja, jedno je ugrađeno u sam Toad (slučajno ili namjerno), dok je drugo online web servis:

1. http://damir-vadas.blogspot.com/2013/06/retrive-oracle-password-from-toad-for.html?showComment=1381689078487#c7070601693746741997

2. http://www.talkingbyte.com/index.php?page=connectionpwds

Ovim putem zahvaljujem autorima na trudu i nesebičnosti!!!

 


Zasto je super-kljuc super stvar?

Monday, 09.09.2013 – Zidar

Svi koji se bavimo bazam podataka znamo sta je kljuc – minimalan skup atributa koji jedinstveno odredjuje entorke (tuples) koji cine telo posmatrane relacije. Minimalan znaci da ako izbacimo neki element iz kljuca, preostali skup vise nije kljuc, jer se gubi jedinstvenost. Kljuc genralno ima vise atributa, a cesto tacno jedan. Sta je onda super-kljuc? Super kljuc je – prosireni kljuc, to jest kljuc kome smo dodali jedan ili vise atributa.

U teoriji, super kljucevi su veoma vazni. A sta nam u praksi znace superkljucevi? Zar nije dovoljno strasno  sto ponekad moramo da koristimo kljuceve od sastavljene od vise atributa? Zasto bi dodavali kljucu jos atributa? Ispostavlja se das u superkljucevi veoma korisna stvar i u praksi.

Dodavanjem atributa kljucevima ne narusava se jedinstvenost. Ako nekakav ID jedinstveno odredjuje redove u nakoj tabeli, onda i kombinacija (ID, Ime) isto tako jedinstveno odredjuje redove u tabeli. Ovo pak znaci da super kljuc mozemo da upotrebimo umesto kljuca, ako nam je tako zgodno.

Pokazacemo dva primera gde superkljucevi znacajno olaksavaju odrzanje integriteta i kvaliteta podataka koje cuvamo u bazi.

Primer 1 – generalizacija.

Neka imamo relaciju koja sdrzi podatke o knjigama u biblioteci. Predikat P koji opisuje relaciju glasi:

P = “Knjiga sa identifikacioniom brojem [ISBN] ima naslov [Title] cuva se u formatu [Format]” . Kljuc relacije je [ISBN]. Format moze imati vrednosti iz skupa {‘mp3′,’printed’}

Iz ovog predikata se mogu izvesti sledece propozicije (iskazi) koji cine telo relacije:

Knjiga [ISBN=9000] ima naslov [Title='An Introduction To Database Systems'] i cuva se u formatu [Format='mp3']

Knjiga [ISBN=75284] ima naslov [Title='Database Design for Mere Mortals'] i cuva se u formatu [Format='printed']

Knjiga [ISBN=53495] ima naslov [Title='SQL Antipatterns'] i cuva se u formatu [Format='printed']

Umesto da pisemo iskaze koji odgovaraju datom predikatu, naravno da je lakse prikazati sve u tabelarnoj formi:

RELATION Books:

[ISBN] [Title] [Format]
9000 An Introduction To Database Systems mp3
75284 Database Design for Mere Mortals printed
53495 SQL Antipatterns printed

Primary Key PK = {ISBN}

Naslovni red u tabeli predstavlja zaglavlje (heading) relacije, a redovi sa podacima predstavljaju telo relacije. Tablea koju smo nacrtali je slika relacije R koju smo definisali predikatom P.

Posto knjige dolaze u razlicitim formatima (tacno dva u nasem slucaju), mi zelimo da za razlicte formate cuvamo razlicte informacije. Za format ‘printed’ hocemo da cuvamo broj stranica i vrstu poveza. Za format ‘mp3′ hocemo da cuvamo velicnu u kilobajtima. Da to postignemo, mozemo da napravimo jos dve relacije, sa ovakvim predikatima:

Predikat PS: “Knjiga [ISBN] ima [Pages] stranica i ima povez [Binding]

Predikat PMP3: “Knjiga [ISBN] zahteva [KB] kilobajta na elektronskim medijima

Slike relacija koje definisanih predikatima PS i PS3 izgledale bi ovako:

RELATION PrintedBooks:

[ISBN] [Pages] [Binding]
75284 612 paper-back
53495 334 hard cover

Primary key PK = {ISBN}

Foreign Key FK = {ISBN} REFERENCES Books {ISBN}

RELATION BooksMP3:

[SBN] [KB]
9000 12350

Primary key PK = {ISBN}

Foreign Key FK = ISBN REFERENCES Books {ISBN}

Relacije su perfektno normalizovane i sve izgleda OK. Ipak, imamo jedan ozbiljan problem. Ja sam pazljivo uneo stampane knjige u relaciju PrintedBooks i knjigu ISBN = 9000 u relaciju BooksMP3. Da nisam bio pazljiv, mogao sam da unesem knjige u pogresne relacije. Kako da garantujem da ce u PrintedBooks biti unesene samo one knjige koje su u format ‘printed’, I das vi MP3 idu u relaciju BooksMP3? Odgovor je – super kljuc, uz jedan CHECK constraint.

Na relaciji Books, definisacemo super kljuc SK1 = {ISBN,Format}. Relacija sada izgleda ovako:

RELATION Books:

[ISBN] [Title] [Format]
9000 An Introduction To Database Systems mp3
75284 Database Design for Mere Mortals printed
53495 SQL Antipatterns printed

Primary Key PK = {ISBN}

Super key SK1: UNIQUE {ISBN,Format}

Relacije PrintedBooks I BooksMP3 prosiricemo zap o jedan novi atribut – [Format], ovako:

RELATION PrintedBooks:

[ISBN] [Pages] [Binding] [Format]
75284 612 paper-back printed
53495 334 hard cover printed

Primary key PK = {ISBN}

Foreign Key FK = {ISBN} REFERENCES Books {ISBN,Format}

CHECK [Format] = ‘printed’

RELATION BooksMP3:

[SBN] [KB] Format
9000 12350 mp3

Primary key PK = {ISBN}

Foreign Key FK = {ISBN} REFERENCES Books {ISBN,Format}

CHECK [Format] = ‘mp3′

Superkljuc SK1 na relaciji Books treba nam da bi mogli da uspostavimo Foreign Key u relacijama PrintedBooks i BooksMP3. CHECK constraints garantuju da samo knjige sa korektnim formatom mogu da idu relacije PrintedBooks i BooksMP3.

Da budemo inzenjerski precizni, trebalo bi da azuriramo i predikate koji idu uz tabele PrintedBooks i BooksMP3, ovako:

Predikat PS: “Knjiga [ISBN] je formata [Format='printed'] , [Pages] stranica i ima povez [Binding]

Predikat PMP3: “Knjiga [ISBN] cuva se u formatu [Format='mp3'] i zahteva [KB] kilobajta na elektronskim medijima

Slucaj koji smo opisali zove se generalizacija, preciznije “Relacija Books je generalizacija relacija PrintedBooks i BooksMP3 po atributu [Format]”

Primer 2: Dozvoljeni iznos za povlacenje na bankovnoj masini

Svaki vlasnik tekuceg racuna moze da na bankovnoj masini povuce odredjenu sumu novca. Iznos koji se moze povuci u jednoj transakciji odredjuje se za svaki racun posebno. Kako garantovati da niko ne moze u jednoj transakciji da povuce vise nego sto mu je dozvoljeno? Narvno – uz pomoc super kljcuceva.

Predikat R1: “Racun broj [AcctNo] ima ogranicenje za podizanje novca u jednoj transakciji of [MaxAmt] dinara”

RELATION Accounts:

[AcctNo] MaxAmt
A1 100
A2 150
A3 50

Primary Key PK = {AcctNo}

Predikat R2: “U transakciji [TrasnsID] u datum i vreme [TransDate] sa racuna [AcctNo] podignuto je [Amt] dinara”

RELATION: Transactions

[TransId] [TransDate] [AcctNo] [Amt]
T1 D1 A1 70
T2 D2 A2 130
T3 D1 A3 45

Primary key PK =:{ TransID}

Alternate Key AK1 = {[AcctNo],[Transdate]}

Foreign Key FK1 =  {[AcctNo]} REFERENCES Accounts {[AcctNo]}

Ponovo je sve perfektno normalizovano. I ponovo imamo problem – kako garantovati da relacija nece prihvatiti vrednosti vece od dozvoljenih u atributu [Amt]?

Uradicemo istu stvar kao u slucaju sa generalizacijom:

  • Uvodimo super kluc u relaciji Accounts, {AcctNo, MaxAmt}
  • Dodajemo atribut [MaxAmt] u relaciju Transactions
  • Azuriramo Foreign Key u relaciji Transaction
  • Dodajemo CHECK constraint u relaciju Accounts koji poredi [Amt] se [MaxAmt]

Konacne relacije izgledace ovako:

RELATION Accounts:

[AcctNo] [MaxAmt]
A1 100
A2 150
A3 50

Primary Key PK = {AcctNo}

Super Key SK1 = {AcctNo, MaxAmt}

RELATION: Transactions

[TransId] [TransDate] [AcctNo] [Amt] [MaxAmt]
T1 D1 A1 70 100
T2 D2 A2 130 150
T3 D1 A3 45 50

Primary key PK =:{ TransID}

Alternate Key AK1 = {[AcctNo],[Transdate]}

Foreign Key FK1 = { [AcctNo],[MaxAmt]} REFERENCES Accounts ([AcctNo],[MaxAmt]}

CHECK [Amt]<=[MaxAmt]

Azurirani predikati izgledaju ovako:

Predikat R2: “U transakciji [TrasnsID] u datum i vreme [TransDate] sa racuna [AcctNo] podignuto je [Amt] dinara, sto je manje od dozvoljenih [MaxAmt] dinara”

 U oba slucaja koja smo pokazali, konacne relacije su donekle denormalizovane.  Uveli smo redundansu – [MaxAmt] se nalazi u relaciji [Transactions], gde mu nije mesto, ako cemo da doslovno ispostujemo Boyce-Codd normalnu formu. To je cena koju smo morali da platimo da bismo garantovali veoma vazna poslovna pravila. Ovo se moze nazvati i ‘kontrolisana denormalizacija’. Konacan rezultat je skup tabela koje bolje predstavljaju realnost nego formalno perfektno normalizovana shema.

Super kljucevi su ponekad zaista super stvar.


Oracle Database 12c je i službeno objavljena!

Wednesday, 26.06.2013 – Dejan

Ako već niste saznali iz drugih izvora, onda će vas ova vijest obradovati – Oracle database 12c je konačno i službeno objavljena, tj. dostupna za download!

12c_download1


Logiranje izmjene strukture baze – DDL LOGGER

Thursday, 11.04.2013 – mradovan

Modeliranje baze podataka često nije jednokratan posao, uvijek se nađe potreba da se naprave izmjene na dijelovima koda ili strukturi tablica, doda ili oduzme neka kolona u nekoj tablici, izmijeni tip podatka neke kolone, doda ili obriše neki ključ ili index…

Kada se takve izmjene rade nepredviđeno, a ne dokumentiraju se, ili u okolini gdje takve stvari radi više ljudi (namjerno ili slučajno), i kad se to radi ručno kroz komandnu liniju a bez modeliranja u nekom alatu za modeliranje (čiji bi se modeli spremali pod sistemom verzioniranja), mogu dovesti do vrlo nezgodnih situacija u kojima ne znamo tok događaja – tko je, kada i što napravio (i zašto ?).

Čak sam i sam bio u situacijama gdje neke promjene radim na razvoju, pa nakon nekog vremena ne znam šta sam napravio i kojim redoslijedom, ili zaključim da sam otišao pogrešnim putem i da se trebam vratiti nekoliko koraka unatrag, a ne znam točno kako…

Rješenje je vrlo jednostavno – database trigger koji logira sistemske događaje u tablicu DDLOG sa sljedećim kolonama:

  • OWNER (vlasnik objekta)
  • OPERATION (CREATE, ALTER ili DROP)
  • OBJECT_TYPE (procedure, table, trigger,package…)
  • OBJECT_NAME (ime objekta)
  • SQL_TEXT (prvih 1000 znakova sql izraza)
  • SQL_FULLTEXT (kompletni kod izraza)
  • CREATED (vrijeme upisa)
  • CREATED_BY (user koji je pokrenuo operaciju)
  • TERMINAL_NAME (ime računala s kojeg je operacija pokrenuta)
  • TERMINAL_IP (IP adresa računala s kojeg je operacija pokrenuta)
  • SESSIONID (ID sesije u kojoj je operacija izvršena).

Iz drugih korisničkih shema se može raditi select na ovu tablicu uz posjedovanje SELECT ANY TABLE privilegije.

Druga tablica ERRLOG služi za logiranje eventualnih grešaka u samom triggeru.

Priložena je skripta koju je potrebno pokrenuti pod SYS userom, čime se kreira user DDLOGGER, sa tablicom DDLOG:

/********************************************************************************************************************************************
Desc: User for logging changes on database objects: CREATE, ALTER and DROP operations.
Author: Mihael Radovan
Last change: 28.03.2013
********************************************************************************************************************************************/
/*  user with privileges */
CREATE user ddlogger IDENTIFIED BY DDL;
GRANT UNLIMITED TABLESPACE TO ddlogger;

/* error log table */
CREATE TABLE ddlogger.errlog
(tstamp TIMESTAMP DEFAULT systimestamp,
errcode number,
errtext varchar2(500))
NOLOGGING, COMPRESS FOR oltp, NOCACHE, NOMONITORING;

/* err log procedure */

CREATE OR REPLACE PROCEDURE ddlogger.plog(errcode number, errtext varchar2)
IS
  PRAGMA autonomous_transaction;
BEGIN
  INSERT /*+ append */ INTO ddlogger.errlog(errcode, errtext) 
  VALUES (errcode, errtext);
  
  COMMIT;

END plog;
/
/* ddl log table */

CREATE TABLE ddlogger.ddlog (
owner   VARCHAR2(30),
operation   VARCHAR2(30),
object_type VARCHAR2(30),
object_name VARCHAR2(30),
sql_text    VARCHAR2(1000),
sql_fulltext clob,
created TIMESTAMP,
created_by  VARCHAR2(30),
terminal_name VARCHAR2(255),
terminal_ip VARCHAR2(30),
sessionid number)
NOLOGGING, COMPRESS FOR oltp, NOCACHE, NOMONITORING;

/* database trigger */

CREATE OR REPLACE TRIGGER ddlogger.DDL_TRIGGER BEFORE DDL ON DATABASE
DECLARE
  oper varchar2(30);
  l_sql_text ora_name_list_t;
  l_count NUMBER;
  l_sql varchar2(1000);
  errcode number;
  errtext varchar2(500);
BEGIN
  SELECT ora_sysevent
    INTO oper
   FROM DUAL;

   l_count := ora_sql_txt(l_sql_text);

  FOR i IN 1..l_count

  LOOP
      l_sql := l_sql||l_sql_text(i);
  END LOOP;

  IF (oper IN ('CREATE', 'ALTER', 'DROP')) AND (ora_dict_obj_name != ' ddlog') THEN NULL;

   INSERT /*+ append */ INTO ddlogger.ddlog (owner, operation, object_type, object_name, sql_text, sql_fulltext, created, created_by, terminal_name, terminal_ip, sessionid)
   VALUES (ora_dict_obj_owner, oper, ora_dict_obj_type, ora_dict_obj_name, substr(l_sql, 1, 1000), l_sql, systimestamp, user, SYS_CONTEXT ('userenv', 'host'),  SYS_CONTEXT ('userenv', 'ip_address'), SYS_CONTEXT ('userenv', 'sessionid'));
  END IF;

EXCEPTION
  WHEN others THEN
     errcode:= SQLCODE;
     errtext:= SQLERRM;
     plog(errcode, errtext);
END;
/

REGEXP_SUBSTR/REGEXP_INSTR: ORA-01428: argument ‘-1′ is out of range

Monday, 11.02.2013 – Dejan

Programiram ja danas nesto i hocu pri tome koristiti regular expression (REGEXP_SUBSTR, REGEXP_INSTR i REGEXP_REPLACE), ali sam na jednom “problemu” izgubio 3-4 sata i ne mogu da nadjem uzrok te greske… Ni Google mi nije pomogao, MyOracleSupport takodje nista…

Htio sam koristiti opciju “backward search”, tj. da se pattern u stringu trazi unatrag, a ne od pocetka. Dakle, ovaj SQL:

select regexp_instr('Austria01#Vienna01#1130', '#', -1, 1)
from dual;

izbacuje gresku:

ORA-01428: argument '-1' is out of range

Sluzbena dokumentacija prvo kaze:
“position: A nonzero integer indicating the character of source_char where the function begins the search. When position is negative, then the function counts and searches backward from the end of string.

A na drugom mjestu samo:
“position is a positive integer indicating the character of source_char where Oracle should begin the search.”

Dakle, sta je od ovih tvrdnji u sluzbenoj dokumentaciji tacno!?

Kao sto rekoh, pretragom interneta nisam nasao nikakve korisne informacije, tako da sam kreirao Service Request kod Oracle Support, pa cemo vidjeti sta ce oni reci…

Stay tuned.

Edit 21.02.2013.:
nakon prepiske sa Oracle Supportom, ustanovljeno je da je dokumentacija pogresna. :)
Ovo su mi javili:

“Hello,

the new doc bug 16374293 has been created and it was already screened for DBE, then it will be processed in accord with its priority and the next Olap guides will be corrected.

Thanks for your hint.”

Znaci, trenutno nije moguce koristiti backward search sa REGEXP komandama…


Druženje u Beogradu?

Saturday, 26.01.2013 – Dejan

Nakon nekoliko seminara u Zagrebu, ovaj put idem na jedan kurs u Beograd: “Oracle Database 11g: Data Guard Administration Rel 2″, jer mi je potreban kao uslov za polaganje OCM (Oracle Certified Master) ispita.
Dakle, od 31.03.2013. do 04.04.2013. sam u Beogradu, pa ako je neko za druženje uz pivo/nespresso/ćevape/Sushi i ostale delikatese, nek se javi!


Full Table Scan vs. BITMAP Index vs. VIRTUAL Column

Friday, 02.11.2012 – Dejan

Ovaj put donosim još jedan primjer iz prakse, na osnovu kojeg ću pokazati interesantne metode optimizacije problematičnog SQL upita.

U stvarnoj bazi postoji jedna tabela, u koju se podaci unose i obrađuju po slijedećem principu:
- podaci se unose u nejednakim razmacima, pri čemu se jedna status kolona označi sa ‘N’, što znači da podaci nisu obrađeni; ukoliko dođe do neke greške prilikom unosa ili su podaci nepotpuni, onda status kolona dobija vrijednost NULL
- jedan SQL upit se izvršava svakih 5 sekundi i provjerava, da li postoje neobrađeni ili nepotpuni podaci
- ukoliko postoje neobrađeni podaci, onda bivaju obrađeni, nakon čega se vrijednost u status koloni mijenja iz ‘N’ u ‘Y’

E sad, ostavimo na stranu što je dizajn ove tabele, odnosno njena fizička struktura, u praksi veoma loša…

Zadatak je da optimiram onaj SQL, koji svakih 5 sekundi provjerava, da li postoje neobrađeni podaci. Možeš se žaliti da je struktura tabele loša i da ju treba izmijeniti – odgovor je uvijek isti:”Nemamo sad vremena za komplikovane izmjene, moramo do kraja mjeseca završiti druge bitnije stvari, a to ćemo naknadno…bla bla“…

Dakle, na posao… Trebalo mi je skoro 2 sata vremena, ali rezultat je bio itekako dojmljiv… Zanima vas kako?
Pročitaj kompletan tekst »


Interval partitioning: zašto i kako?

Saturday, 27.10.2012 – Dejan

Zašto?

Slagaću ako kažem, da nisam početkom skoro svake godine nailazio na grešku “ORA-14400: inserted partition key does not map to any partition“. Uvijek, ali uvijek! neko od programera zaboravi kreirati particiju za MAXVALUE ili particije i za narednu godinu, pa poslije Nove godine bude frka i panika, kad aplikacija ne radi, a telefon zvoni, dok preko E-Maila šalju screenshotove sa greškom… Na svu sreću, Oracle je tom problemu izašao u susret i omogućio opciju “Interval partitioning“, pomoću koje se nove particije automatski kreiraju.

Naravno kao i uvijek ću na praktičnom primjeru pokazati i objasniti, kako se interval partitioning podešava, kao i osnovne naredbe za rad sa particijama i subparticijama u tom slučaju.
Pročitaj kompletan tekst »


Preglednost kôda: IF var1,…,varN IS NOT NULL … vs. COALESCE(var1, var2,…, varN)

Wednesday, 24.10.2012 – Dejan

Po ko zna koji put vidjam u PL/SQL procedurama aljkav kôd i ne mogu se nacuditi raznim improvizacijama i perverzijama, koje pojedini programeri pisu…

Jedna od zadnjih se protezala na 90 linija kôda i izgledala je ovako:

IF var1 IS NOT NULL THEN varResult := var1;
ELSIF var2 IS NOT NULL THEN varResult := var2;
...
ELSIF varN IS NOT NULL THEN varResult := varN;
END IF;

Mislim, cemu to!? Shvatio sam da je cilj provjeriti varijable jednu po jednu, i cim se dodje do prve varijable, koja ima neku vrijednost, dodijeliti ju rezultatskoj varijabli. Zar nije ovako preglednije?

varResult := COALESCE(var1, var2, ..., varN);

FLASHBACK DATABASE glavu čuva!

Tuesday, 23.10.2012 – Dejan

Zašto Flashback?

Sigurno ste se već našli u situaciji da imate veoma kratak “maintenance window” u sklopu kojeg se vrše neke izmjene nad bazom, npr. instaliranje novog patcha, novi release ogromne aplikacije ili neka slična operacija, koja bi mogla biti kritična, što znači, da bi u slučaju neke greške ili neželjenog rezultata morali vratiti bazu u prvobitno stanje, dakle prije te izmjene.

U mnogim slučajevima se previdi taj “fallback” scenario, pa Oracle DBA radi restore kompletne baze… A to traje, pogotovo ukoliko je baza velika… Taman ste pomislili:”Još ova sitnica, 5-10 minuta i gotovo!“, kad ono cvrc! Greška. Panika. Psovanje. Restore baze. Pa se onda češkate po glavi i nestrpljivo čekate kad će restore biti okončan…

Taaa-daaam!

Od sad, pa nadalje i ubuduće za većinu tih “maintenance taskova” (plaćam pivo i ćevape za iole smislen prevod ovih riječi!) možete koristiti Flashback tehnologiju! Ukratko, Flashback omogućava “povratak u prošlost” do nekog zadanog trenutka.

Dakle, prije nego što započnete sa izmjenama na bazi, aktivirate Flashback i postavite tačku (“RESTORE POINT“) do koje želite vratiti bazu ukoliko dođe do nekih problema.

Kako Flashback?

Pokazaću kako se Flashback aktivira, kako se postavlja RESTORE POINT i kako se koristi za vraćanje kompletne baze do te tačke.

1. Da bi Flashback mogao biti aktiviran, baza mora biti u ARCHIVELOG režimu rada. Provjeriti parametre i ukoliko je potrebno, prebaciti bazu u ARCHIVELOG režim. U suprotnom, preskočite taj korak.

SQL> select log_mode, flashback_on from v$database;

LOG_MODE     FLASHBACK_ON
------------ ------------------
NOARCHIVELOG NO

SQL> sho parameter db_recovery_file_dest

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_recovery_file_dest                string      D:\_Oracle_\app\flash_recovery_area
db_recovery_file_dest_size           big integer 3912M


SQL> shut immediate
Database closed.
Database dismounted.
ORACLE instance shut down.

SQL> startup mount
ORACLE instance started.

Total System Global Area 2572144640 bytes
Fixed Size                  2178496 bytes
Variable Size            1811939904 bytes
Database Buffers          738197504 bytes
Redo Buffers               19828736 bytes
Database mounted.
SQL> alter database archivelog;

Database altered.

SQL> alter database open;

Database altered.

2. Potrebno je obavezno podesiti dva parametra u bazi: veličinu i lokaciju za Flashback arhivu:

SQL> alter system set DB_RECOVERY_FILE_DEST_SIZE=10G scope=BOTH;

System altered.

SQL>  alter system set db_recovery_file_dest='D:\_Oracle_\app\flash_recovery_area' scope=BOTH;

System altered.

Parametri moraju ostati permanentno u SPFILE ili u init.ora datoteci, da se ne bi nakon restarta baze izgubili. Ako ne stavite “scope=BOTH” ili ukoliko u init.ora datoteci ne sačuvate te parametre, onda ćete nakon restarta baze dobiti slijedeću gresku:

SQL> flashback database to restore point BEFORE_CHANGE;
flashback database to restore point BEFORE_CHANGE
*
ERROR at line 1:
ORA-00283: recovery session canceled due to errors
ORA-38770: FLASHBACK DATABASE failed during recovery.
ORA-38760: This database instance failed to turn on flashback database

a u alert logu ćete pronaći ove greske:

Thu Oct 25 09:45:09 2012
ALTER DATABASE   MOUNT
Successful mount of redo thread 1, with mount id 684437221
Allocated 14761792 bytes in shared pool for flashback generation buffer
Starting background process RVWR
Thu Oct 25 09:45:14 2012
RVWR started with pid=18, OS id=58916978
RVWR could not begin generation of flashback log data because
DB_RECOVERY_FILE_DEST is not set.
Errors in file ..._rvwr_58916978.trc:
ORA-38776: cannot begin flashback generation - recovery area is disabled
Database mounted in Exclusive Mode
Lost write protection disabled
Completed: ALTER DATABASE   MOUNT
Thu Oct 25 09:45:24 2012
flashback database to restore point BEFORE_CHANGE
Flashback Restore Start
Thu Oct 25 09:46:18 2012
Flashback Restore Complete
Flashback Media Recovery Start
 started logmerger process
Thu Oct 25 09:46:18 2012
Slave exiting with ORA-38770 exception
Errors in file ..._pr00_24903742.trc:
ORA-38770: FLASHBACK DATABASE failed during recovery.
ORA-38760: This database instance failed to turn on flashback database
Recovery Slave PR00 previously exited with exception 38770
Flashback Media Recovery failed with error 10879
ORA-283 signalled during: flashback database to restore point BEFORE_CHANGE...

3. Aktiviranje Flashback-a i postavljanje tačke povratka:

3.1. U verziji 10g baza mora biti u MOUNT režimu, da bi se Flashback mogao aktivirati:

SQL> shut immediate
Database closed.
Database dismounted.
ORACLE instance shut down.

SQL> startup mount
ORACLE instance started.

Total System Global Area 2572144640 bytes
Fixed Size                  2178496 bytes
Variable Size            1811939904 bytes
Database Buffers          738197504 bytes
Redo Buffers               19828736 bytes
Database mounted.

SQL> alter database flashback on;

Database altered.

SQL> create restore point BEFORE_CHANGE guarantee flashback database;

Restore point created.

SQL> alter database open;

Database altered.

3.2. U verziji 11gRel2 baza ne mora biti u MOUNT režimu, tako da odmah možemo aktivirati Flashback i postaviti RESTORE POINT:

SQL> alter database flashback on;

Database altered.

SQL> create restore point BEFORE_CHANGE guarantee flashback database;

Restore point created.

SQL> col name for a25
SQL> col time for a34
SQL> set lines 180
SQL> select SCN, NAME, GUARANTEE_FLASHBACK_DATABASE as GUA, STORAGE_SIZE, TIME
 from v$restore_point;

       SCN NAME               GUA STORAGE_SIZE TIME
---------- ------------------ --- ------------ ----------------------------------
   1673006 BEFORE_CHANGE      YES     15941632 23-OCT-12 10.00.42.000000000 PM

4. Napravimo neku izmjenu u bazi – za ovaj primjer ću samo kreirati jedan tablespace i jednog korisnika:

SQL> create tablespace dejan 
datafile 'D:\_ORACLE_\APP\ORADATA\DWHTEST\dejan.dbf' size 16M autoextend off 
extent management local segment space management auto;

Tablespace created.

SQL> create user dejan identified by dejan default tablespace users temporary tablespace temp;

User created.

Opcionalno možete povećati “retention time”, ukoliko taj “maintenance task” traje duže od jednog dana. Standardno je parametar “db_flashback_retention_target” postavljen na 1440 minuta, odnosno jedan dan, pa ga po potrebi povećajte:

SQL> sho parameter flashback

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_flashback_retention_target        integer     1440 

SQL> alter system set db_flashback_retention_target=2880;

System altered.

5. Ok, gotovi smo sa izmjenama, pa možemo ili vratiti bazu u prvobitno stanje ukoliko se pojavila neka kritična greška, ili deaktivirati Flashback i obrisati RESTORE POINT:

5.1. Vraćanje baze u prvobitno stanje:

SQL> shut immediate
Database closed.
Database dismounted.
ORACLE instance shut down.

SQL> startup mount
ORACLE instance started.

Total System Global Area 2572144640 bytes
Fixed Size                  2178496 bytes
Variable Size            1811939904 bytes
Database Buffers          738197504 bytes
Redo Buffers               19828736 bytes
Database mounted.

SQL> flashback database to restore point BEFORE_CHANGE;

Flashback complete.

SQL> alter database open resetlogs;

Database altered.

SQL> alter database flashback off;

Database altered.

SQL> drop restore point BEFORE_CHANGE;

Restore point dropped.

5.2. Sve je u redu, nastavljamo u revijalnom tonu:

SQL> alter database flashback off;

Database altered.

SQL> drop restore point BEFORE_CHANGE;

Restore point dropped.

6. OBAVEZNO!!!! uraditi full backup baze, zato što smo napravili novu inkarnaciju baze sa ALTER DATABASE OPEN RESETLOGS.

Eto, pa vi sad usporedite vrijeme potrebno za restore kompletne baze i vrijeme potrebno da se baza pomoću Flashback tehnologije vrati u prvobitno stanje.