SQL*Plus 12.2

giovedì 20 aprile 2017 alle 20:10 | Pubblicato su 12c, SQL, Varie | 1 commento
Tag:

Oggi ho provato a installare la versione 12.2 del nuovo instant client Oracle versione 12.2 sul mio pc aziendale con sistema operativo Win7. Non ci sono motivi particolari per cui ci sia la necessità di passare ad usare questa versione se non al puro scopo di testarla e tal proposito mi sono ricordato di un post di Mike Dietrich (anche perché l’ho letto ieri 🙂 ) dove si parla che una fra le novità di questa versione di SQL*Plus è la diversità di comportamento nel caricamento del file “login.sql”. Io normalmente uso sul mio pc una configurazione per cui lancio uno script .cmd che a sua volta chiama un’altro script che setta le opportune variabili d’ambiente, fra cui SQLPATH affinché punti a una directory dove trovo una serie di script di utilità (per molti dei quali vanno i ringraziamenti a Tanel Poder)  e l’utilissimo login.sql che imposta l’ambiente iniziale per SQL*Plus come garba a me. Con la nuova versione di SQL*Plus effettivamente l’esecuzione automatica di login.sql che si trova sotto il percorso puntato dalla variabile d’ambiente SQLPATH non funziona. Infatti il post di Franck Pachot cui fa riferimento Dietrich fa tutti i test dettagliati su ambiente Linux, peccato però che come scrive Dietrich alla fine del suo post:

On Windows please be aware of (credits to Tim Hall):

  • Bug 25804573SQL PLUS 12.2 NOT OBSERVING SQLPATH IN REGISTRY OR ENV VARIABLE FOR LOGIN.SQL

 

Ti pareva se su Winzoz non c’era qualche fastidio…

Sinceramente non mi è chiaro come aggirare il problema, la soluzione che ho adottato io sembra bruttina ma è l’unica che ho trovato in modo veloce: ho rinominato sqlplus.exe in sqlplus_orig.exe, ho creato un file sqlplus.cmd il cui contenuto è:

sqlplus_orig.exe %1 @login

Ora, prima ho provato a non rinominare il file .exe confidando che la logica di ricerca degli eseguibili mettesse prima i .cmd e dopo i .exe ma non sembra esssere così. La cosa che invece mi perplede abbastanza è il fatto che se metto @login.sql non funziona, @login si. Anche se invoco successivamente @login.sql non funziona, funziona se lo invoco con il percorso completo

SYSTEM@svil121 > @login.sql
SYSTEM@svil121 > @c:\oracle\conf\login.sql

PL/SQL procedure successfully completed.


Session altered.

Questa particolarità vale solo per il file login.sql, gli altri script funzionano sia che metta l’estensione  e sia che non la metta

 

 

Annunci

Campi varchar2 con stringhe vuote

mercoledì 7 ottobre 2015 alle 07:14 | Pubblicato su PL/SQL, SQL, Varie | Lascia un commento

Post molto sintetico:


set serveroutput on size unlimited

declare
a varchar2(10);
begin
a := '';
if (a is null) then dbms_output.put_line('empty = null');
else dbms_output.put_line('empty is not null');
end if;
if (a = '') then dbms_output.put_line('empty = empty');
else dbms_output.put_line('empty <> empty');
end if;
a := null;
if (a is null) then dbms_output.put_line('empty = null');
else dbms_output.put_line('empty is not null');
end if;
if (a = '') then dbms_output.put_line('empty = empty');
else dbms_output.put_line('empty <> empty');
end if;
end;

TEST@test112 > /
empty = null
empty <> empty
empty = null
empty <> empty

Soluzioni di Virtualizzazione dei dati

giovedì 8 gennaio 2015 alle 08:21 | Pubblicato su cloud, Diario, Varie, virtualizzazione | Lascia un commento
Tag:

Negli ultimi tre/quattro anni sono stato molto pigro o forse solamente preso da altri impegni, sia lavorativi che extralavorativi, fatto sta che ho dedicato molto meno tempo di quanto non ne dedicassi prima all’approfondimento di nuove tematiche tecnologiche e al rimanere per quanto possibile informato sull’andamento della tecnologia almeno nel settore più vicino a quello in cui lavoro, quindi sintetizzando ai sistemi di gestione delle basi di dati. A peggiorare la situazione è arrivata sei mesi fa una batosta personale che oltre a mettere a dura prova il mio morale e le mie motivazioni ha ridotto ulteriormente il mio tempo libero a disposizione per questa attività di formazione continua. Oggi ho trovato il tempo per dedicarmi all’esplorazione degli articoli “non letti” presenti sulla mia sezione feedly, articoli che si sono accumulati ormai da mesi, anche se noto una scarsa attività.

Oggi ho letto questo articolo di Kyle Hailey intitolato “Top 3 criteria to choose a data virtualization solution”. Quando ho iniziato a leggerlo non avevo neanche idea di che cosa si intendesse  per “data virtualizzation solution”, man mano che leggevo l’articolo pensavo a quanto la tecnologia in questo campo deve essere avanzata in questi ultimi anni, praticamente senza che io me ne accorgessi. D’accordo, è un settore che effettivamente io per ora posso guardare solo da fuori, forse la mia azienda ancora non ha dimensioni tali da sentire l’esigenza o la necessità di questo tipo di soluzioni, anche se posso immaginare che andando le cose come sono andata negli ultimi anni tale esigenza potrà a breve sorgere. In ogni caso la letture di questo articolo è stata per me stimolante, anche se non entra in nessun dettaglio, fa un ottimo riassunto delle caratteristiche che ci si può aspettare di trovare e quindi ottenere oggi con questi sistemi di virtualizzazione dei dati, che in pratica estendono di molto il concetto di snapshot gia presente sulle SAN e su alcuni tipi di filesystem gia da anni. Hailey scrive che ci sono sistemi che permettono di fare dei “branch” dei dati, che tali branch possono essere fatti in modo efficente sia in termini di tempo che di spazio occupato, un po’ come facciamo normalmente con il sistema di gestione del codice sorgente ad esempio con Subversion.

In effetti anche nella mia piccola esperienza mi ritrovo con la problematica di avere più copie e versioni degli stessi dati, solitamente i database si moltiplicano, ambienti di sviluppo, di test, di integrazione, di UAT, di demo ecc. Questo viene gestito nel mio caso con dump di schemi di database Oracle che vengono creati e importati qua e la.

Si tratta di un argomento che ho trovato interessante, per questo ho voluto scriverne qualcosa, se non altro per tenere una traccia anche dell’interessante articolo di Kyle Hailey, se qualcuno mi dovesse chiedere qualcosa in futuro sui sistemi di virtualizzazione dati o CDM o CDV o DVA forse potrò dare una risposta diversa dal solito: “mai sentito prima ” 🙂

Inghippi con il Character Set – Conclusione

giovedì 1 agosto 2013 alle 01:23 | Pubblicato su 11g, Diario, SQL, Varie | Lascia un commento
Tag:

Un titolo decisamente ottimista per un post su questo argomento, la mia speranza è comunque di chiudere l’argomento ripreso non molto tempo fa con il post “Inghippi con il Charcter SET“.  L’ispirazione mi è venuta leggendo la nota del supporto Oracle

NLS_LANG Explained (How does Client-Server Character Conversion Work?) (Doc ID 158577.1)

che a sua volta mi ha rimandato alla nota:

The correct NLS_LANG in a Microsoft Windows Environment (Doc ID 179133.1)

Entrambe le note precisano che per gestire in modo corretto il character set è meglio utilizzare SQL Developer, però danno anche altri spunti interessanti. Ad esempio viene specificato:

The “Unicode” “chcp 65001” and “chcp 65000” values are NOT supported with sqlplus.exe.

Poi usano un character set che forse non avevo mai notato: WE8PC850 che pare andare molto d’accordo con il CP 850 settato di default sulle macchine Windows.

Sempre adottando i corretti settaggi ho verificato che si può aggirare i limiti di sqlplus adottando comandi registrati su file e poi invocandoli da sqlplus tramite il comando START, bisogna però fare attenzione alla codifica del file su cui si salvano i comandi, ecco  un esempio:

C:\tmp>chcp 65001
Tabella codici attiva: 65001

C:\tmp>set NLS_LANG=.AL32UTF8

C:\tmp>more insert_test_charset.sql
Memoria insufficiente.

C:\tmp>SQLPLUs sviluppo50/sviluppo50@svil112_methone

SQL*Plus: Release 11.2.0.3.0 Production on Thu Aug 1 13:17:23 2013

Copyright (c) 1982, 2011, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 – 64bit Production
With the Partitioning, Data Mining and Real Application Testing options
PL/SQL procedure successfully completed.
Session altered.

SVILUPPO50@svil112_methone > delete from test_charset;

8 rows deleted.

SVILUPPO50@svil112_methone > @insert_test_charset.sql

1 row created.
1 row created.

SVILUPPO50@svil112_methone > SELECT * FROM TEST_CHARSET;

A
—————————————————————————————————-
KKKKà
NNNè

SVILUPPO50@svil112_methone >

Il file è formato utf-8 (senza il famigerato BOM) e si noti come il comando more fallisca con il messaggio “memoria insufficente”

Il contenuto del file insert_test_charset.sql è:

INSERT INTO TEST_CHARSET VALUES (‘KKKKà’);
insert into test_charset values (‘NNNè’);

In realtà poi, lavorando con caratteri compresi nella codifica West-Europe, usare UTF-8 lato client nel mio caso è superfluo, credo che d’ora in poi userò WE8PC850

Ancora Character Set, ORA-00600 [kafspa:columnBuffer2]

giovedì 1 agosto 2013 alle 01:55 | Pubblicato su 11g, Diario, Installation and Configuration, Varie | Lascia un commento
Tag: , ,

Non c’è dubbio che la gestione del Character Set sui database Oracle sia una cosa tutt’altro che banale e poco chiara ai più. Ieri controllando i log di un database interno utilizzato per i test ho trovato il seguente errore:

ORA-00600: internal error code, arguments: [ORA-00600: internal error code, arguments: [kafspa:columnBuffer2], [4053], [4000], [], [], [], [], []

Il database è un 10.2.0.5 su linux 64 bit, recentemente migrato da una vecchia macchina dove c’era però una versione 10.2.0.3. Ho passato i dati dal vecchio database al nuovo tramite expdp/impdp dei vari schemi (approfittando per fare un po’ di pulizia). L’errore veniva generato durante il calcolo delle statistiche notturno e nell’alert.log c’era rimando a un file di trace su cui ho trovato anche dettagli sulla tabella che provocava l’errore. Il secondo e terzo argomento dell’errore ORA-00600 mi ha fatto subito sospettare il tipo di problema (che fra l’altro in forme diverse ho gia incontrato altre volte. In effetti ho individuato nella tabella un campo definito come VARCHAR2(4000) facendo una query simile a questa:


SELECT NOMECAMPO FROM NOMETABELLA WHERE LENGTH(NOMECAMPO)>4000

ottenevo sempre l’errore  ORA-00600.

Facendo una ricerca sul supporto Oracle ho trovato poco, facendone una Google sono arrivato qui, come dire: a volte ritornano. Infatti in coda al post che non ricordavo di aver gia letto ho trovato dei miei commenti. Avendo anche cambiato il titolo del blog non mi ricordavo neanche chi fosse l’autrice 🙂

In realtà ho scoperto con un po’ di sorpresa che lo schema proveniva in effetti da un dump fornitoci dal cliente, che però io credevo avesse database con character set UTF-8 solo di recente sono riuscito a scoprire che in realtà il cliente utilizza charset ISO8859-15 e che quindi ero incappato sullo stesso problema. Il bello è che per trovare una soluzione, dopo alcuni banali tentativi per isolare i record con stringhe lunghe più di 4000 byte all’interno del campo incriminato, ho provato a fare un export con data pump e importare la tabella su un’altro schema dello stesso database, con una certa sorpresa mi sono trovato sul nuovo schema una copia della tabella con lo stesso problema.

Dopo vari esperimenti, alla fine, sfruttando la chiave primaria della tabella, che è un id generato da sequence,  ho isolato un record con il problema; in realtà ho trovato anche altri 6 record che su un campo varchar2(600) avevano stringhe che occupavano ben più di 600 byte ma questi record creavano problemi solo nei tentativi di CREATE TABLE AS …

In teoria ho risolto facendo un update sul campo per chiave:


UPDATE NOMETABELLA SET NOMECAMPO=SUBSTR(NOMECAMPO,1,4000) WHERE CAMPOCHIAVE=XXX

che con un certo mio sconcerto ha funzionato (apparentemente), in seguito ho fatto alcune prove, compreso il ricalcolo delle statistiche, senza riscontrare problemi, stamattina però nell’alert.log ho ritrovato l’errore sulla stessa tabella, in realtà mi aspettavo di trovare l’errore sulla copia che ho mantenuto con l’errore per fare ulteriori verifiche è così è stato anche se in un primo momento non era chiaro guardando il trace.

Stamattina ho avuto modo di fare ricerche più approfondite e mirate sul problema, leggendo nota del supporto Oracle intitolata:

“Changing the NLS_CHARACTERSET From AL32UTF8 / UTF8 (Unicode) to another NLS_CHARACTERSET (Doc ID 1283764.1)”

al paragrafo 1.d ho trovato la seguente frase:

Do NOT use Expdp/Impdp when going from (AL32)UTF8 to a single byte NLS_CHARACTERSET on ALL 10g versions lower then 10.2.0.4 (including 10.1.0.5). Also 11.1.0.6 is affected.
It will provoke data corruption unless Patch 5874989 is applied on the Impdp side. Expdp is not affected, hence the data in the dump file is correct.Also the “old” exp/imp tools are not affected.
This problem is fixed in the 10.2.0.4 and 11.1.0.7 patch set.
Fixed in 11.2.0.1 and up

 

che mi ha un po’ illuminato. In realtà ho dovuto un po’ ricostruire la storia. Sul nostro nuovo database di test 10.2.0.5 (che dovrebbe essere esente dal bug) ho due schemi dello stesso cliente, uno importato direttamente dal dump fornito dal cliente e su cui non si presenta il problema, infatti nei log dell’import trovo:

ORA-02374: conversion error loading table “SCHEMA2″.”NOMETABELLA”
ORA-12899: value too large for column NOMECAMPO (actual: 3995, maximum: 4000)
ORA-02372: data for row:

L’altro schema, sui ho trovato il problema, proveniva dallo stesso dump, ma era passato prima dal vecchio database 10.2.0.3, quindi era stato importato sul vecchio db, dove si era generata la corruzione (senza che io me ne accorgessi), poi da li è stato esportato  e importato sul nuovo database, senza errori nei log di data pump. Mi pare quindi che Oracle abbia corretto parzialmente il problema, perché impdp non genera più la corruzione sulla tabella ma scarta i dati in importazione, però, se la tabella è gia corrotta essa viene esportata e importata da datapump tale e quale, corruzione compresa. Prossimamente conto di provare a fare dei test su un Oracle 11.2.0.3, magari se ne trovo uno con character set ISO8859 posso fare dei test più completi.

Riguardo la gestione del character set su Oracle riporto qui un paio di riferimenti a note Oracle che vale la pena leggere:

  • AL32UTF8 / UTF8 (Unicode) Database Character Set Implications (Doc ID 788156.1)
  • Changing the NLS_CHARACTERSET From AL32UTF8 / UTF8 (Unicode) to another NLS_CHARACTERSET (Doc ID 1283764.1)
  • NLS_LANG Explained (How does Client-Server Character Conversion Work?) (Doc ID 158577.1)

SQL Developer 3.1.07 e SDO_GEOMETRY

lunedì 14 maggio 2012 alle 14:39 | Pubblicato su Diario, Varie | Lascia un commento

Non tanto tempo fa mi sono accorto che  nel febbraio scorso Oracle ha rilasciato una nuova versione di SQL Developer, allora io fiducioso l’ho subito scaricato e configurato sul mio PC. Qualche tempo dopo però mi sono trovato a interrogare una tabella oracle con dati “spaziali”, ciò con tipo dato SDO_GEOMETRY, si trattava di una tabella con pochi record ed avevo la necessità di esportarli in forma di “INSERT”, peccato però che sia nell’output che nell’esportazione il mio nuovissimo SQL Developer anziché i dati veri e propri al posto del campo  di tipo SDO_GEOMETRY  SQL Developer mi mettesse la costante  ‘[MDSYS.SDO_GEOMETRY]’.  Manco a dirlo è l’ennesimo baco introdotto su SQL Developer, come indicato in questo thread del forum OTN. Per fortuna mi tengo sul pc le ultime 4/5 installazioni di SQL Developer, quindi è stato facile verificare che con la precedente versione, la 3.0.04 il problema non si presenta.

Gestione della memoria in Windows

mercoledì 3 agosto 2011 alle 03:51 | Pubblicato su Linux, Varie | 1 commento
Tag: ,

Se c’è una cosa che per me (e sono certo anche per la stragrande maggioranza degli utenti) rimane un mistero è come gestisce la memoria Windows. Ora, non sono in grado di fare grandi confronti con sistemi linux, perché mentre ormai da anni sono consolidati sistemi Linux a 64 bis, MS ha scoperto l’abbondanza dei bit in tempi più recenti. Avendo avuto recentemente problemi con applicazioni Java che su windows 2003 standard edition non riuscivano ad allocare 1024MB di memoria ho deciso di approfondire un po’ il tema e raccogliere un po’ di informazioni in un post che rimarrà più come storia che di effettiva utilità.

Il caso concreto che mi sono trovato ad affrontare è stato fare funzionare Oracle BI versione 10g per dei test. Questa versione di Oracle BI è certificata al massimo su Windows 2003, peccato al primo tentativo di accesso alla console di amministrazione, gestita dall’application server OC4J installato su una macchina win2003 io abbia avuto un errore per l’impossibilità da parte di Java di allocare memoria. Gli script di avvio di OC4J per default contengono le opzioni


-XX:MaxPermSize=128m -Xmx512m

Ho provato allora a modificare tali impostazioni impostando


-XX:MaxPermSize=128m -Xmx1024m

Ma questo è risultato provocare un errore gia in avvio di OC4J.

Una veloce ricerca sul Web mi ha portato a questo interessante post che da un metodo per verificare quanta memoria al massimo è in grado di allocare Java. Ho potuto fare così test interessanti su varie macchine, verificando che effettivamente su altre macchine win2003 il comando di test fallisce:

C:\Documents and Settings\utente>java -mx768m -XX:MaxPermSize=128m -version
Error occurred during initialization of VM
Could not reserve enough space for object heap
C:\Documents and Settings\utente>java -mx768m -XX:MaxPermSize=64m -version
java version "1.4.2_04"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_04-b05)
Java HotSpot(TM) Client VM (build 1.4.2_04-b05, mixed mode)

In questo caso specifico la macchina ha 2GB di RAM fisica, ma dal task manager risulta usato circa 1,6 GB su 4GB di memoria virtuale.

Nei miei studi giovanili la gestione della memoria virtuale nei sistemi operativi è stata presente, fra l’altro a quei tempi simili dimensioni per la RAM erano fantascienza, però io non ho trovato la spiegazione del fatto per cui in tali condizioni il sistema operativo non è in grado di allocare meno di 1 GB di memoria.

Vincendo la mia pigrizia e la mia repulsione ho fatto ulteriori ricerche ed ho trovato questi riferimenti nella documentazione di MS, “virtual address space” e “Confronto tra le architetture della memoria a 32 a 64 bit“.

Pare che con il flag /3GB nel boot.ini di una macchina con 2,5 GB di RAM le cose migliorino, infatti sono arrivato ad allocare quasi 1,5 GB di heap per la JVM.

L’unica macchina Linux a 32 bit che sono riuscito a trovare è una macchina virtuale su cui ho ottenuto questi risultati:

[oracle@vboxm1 ~]$ java -mx2650m -version
java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) Client VM (build 16.3-b01, mixed mode)
[oracle@vboxm1 ~]$ java -mx2750m -version
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.
[oracle@vboxm1 ~]$ uname -a
Linux vboxm1 2.6.18-194.0.0.0.4.el5 #1 SMP Thu Apr 8 18:20:19 EDT 2010 i686 i686 i386 GNU/Linux
[oracle@vboxm1 ~]$ free
             total       used       free     shared    buffers     cached
Mem:        909120     820564      88556          0      27572     656228
-/+ buffers/cache:     136764     772356
Swap:      1735012          0    1735012


Chiaramente le macchine a 64 bit (anche se non reali come  gli Xeon) simili problemi non si presentano, neanche su win2008 a 64 bit.

A completamento del discorso devo dire che in passato ho avuto anche problemi con oracle database server 10gR2 su windows che in sistemi particolarmente carichi avevo frequenti errori ORA-04030

V$OPEN_CURSOR

martedì 10 maggio 2011 alle 10:41 | Pubblicato su Performance Tuning, Varie | 6 commenti
Tag:

Alcuni giorni abbiamo avuto un problema con l’errore oracle “ORA-01000: maximum open cursors exceeded” e quindi mi è stato chiesto di fare una prova e verificare lo statement legato al cursore che si ipotizzava una procedura non chiudesse.  Raramente ho avuto problemi con questo errore, quando mi è capitato si è riscontrato che effettivamente mancaca una chiamata al metodo java di chiusura dello statement, che corrisponde alla chiusura del cursore Oracle.

Mi è venuta in mente all’uopo la vista di sistema V$OPEN_CURSOR che secondo la documentazione della versione 10gR2 mostra i cursori che ogni sessione ha “correntemente” (currently) analizzato e aperto (opened and parsed). Per evitare che alcune mie traduzioni possano fuorviare dove ho dubbi riporto anche la dicitura originale del manuale. In realtà credo che tale definizione sia fuorviante, perché tale vista mostra i cursori attualmente in cache, senza dare informazione alcuna sul fatto che siano aperti o meno.

Faccio un piccolo passo indietro, cos’è un cursore? Anni fa mi sono scritto una sorta di guida oracle personalizzata e in questa guida mi ricordavo di aver annotato anche queste informazioni, prelevate dal manuale “Concepts” secondo il quale sono collegamenti (handle) a aree di memoria private della sessione, le “private SQL Area” che a seconda della configurazione si trovano nella Shared Pool (server condivisi o shared server) o nella PGA (server dedicati o dedicated server). Il numero massimo di cursori che una sessione può aprire è limitato dall’impostazione del parametro OPEN_CURSORS che ha come valore di default 50 secondo la documentazione ma che io sui miei database (10.2.0.3 e 10.2.0.4) trovo impostati a 300 in quanto pare sia uno dei valore così impostati dal Database Configuration Assistant che solitamente uso per creare i database.

Interrogando la vista V$OPEN_CURSOR per un determinato SID si ottengono normalmente diversi record e ciò mi ha lasciato decisamente spiazzato. Uno dei motivi pare essere l’impostazione del parametro SESSION_CACHED_CURSORS che secondo la documentazione  come default il valore ‘0’ ma che sui miei database ha come default il valore 20. Ciò significa che sulla V$OPEN_CURSOR non vengono visualizzati solo i cursori aperti per ogni sessione, ma anche quelli in cache. L’unica informazione certa che si può avere sui cursori aperti per una sessione, anche secondo la nota del supporto  oracle 743605.1 (occorre un accesso al supporto oracle per visualizzare il link) che conferma quanto ho scritto sopra, è il numero di cursori aperti (salvo bachi), ottenibile con la query:


select a.value, s.username, s.sid, s.serial#
from v$sesstat a, v$statname b, v$session s
where a.statistic# = b.statistic#  and s.sid=a.sid
and b.name = 'opened cursors current'
and a.sid=<SID>;

Anche in una discussione su Asktom mi sembra si affermasse ciò riportanto la stessa query.

Mi rimangono alcune perplessità, interrogando la V$OPEN_CURSOR per una singola sessione posso trovare un numero di record superiore al valore del parametro SESSION_CACHED_CURSOR, alcuni legati allo stesso SID ma a diverso SADDR, colonna i cui significato non è ben chiaro, anche se sospetto sia legata a chiamate ricorsive.

Import tradizionale e cambio tablespace

martedì 15 febbraio 2011 alle 15:30 | Pubblicato su Installation and Configuration, Varie | 3 commenti

Oggi tratto un argomento vecchio, benché Oracle 10g e Data Pump siano stati rilasciati da molti anni e questa utility per esportare su file parti di database sia stabile, comoda e flessibile, mi capita ancora di dover maneggiare file di dump creati con le vecchie versioni del programma di export di Oracle, se non altro perché ho ancora a che fare con database versione 9.2

Più per tradizione e per adeguarci alla richiesta di molti clienti anche noi applichiamo tutt’ora la classica suddivisione di tablespace per i dati e per gli indici, pur non vedendo alcun motivo scientifico per fare ciò. Quando però si fanno export/import di tipo tradizionale, e si vuole mantenere tale suddivisione ma con nomi di tablespace diversi la cosa non è immediata. Con datapump è stato introdotto il comodissimo parametro REMAP_TABLESPACES, ma sul vecchio import non c’è una soluzione diretta, se non ci sono tablespace con lo stesso nome del database di origine, gli oggetti vengono creati sul tablespace di default dello schema su cui si importano gli oggetti. Le tecniche per ovviare a ciò sono diverse, ma ieri ne ho collaudata una che non avevo mai provato e che però mi è sembrata molto comoda, la riassumo brevemente:

1) impostazione per l’utente/schema della tablespace di default quella dei dati (tabelle)

2) importazione del dump senza indici, ovvero con parametro INDEXES=no

3) impostazione per l’utente/schema della tablespace di default quella degli indici

4) importazione del dump senza dati, quindi con parametro ROWS=no IGNORE=yes INDEXES=yes

il parametro IGNORE=yes fa si che l’import non termini con errore perché trova gia le tabelle.

In passato una delle tecniche che ho utilizzato è stata quella di utilizzare il parametro INDEXFILE per generare su file i DDL degli indici, modificare il file opportunamente e lanciare da sqlplus la creazione degli indici, oppure importare tutto e poi spostare gli indici ma quest’ultimo è sicuramente il metodo più scomodo perché richiede di allocare più spazio nella tablespace dei dati e un po’ di manovre per generare lo script di spostamento per tutti gli indici.

Errori pericolosi

lunedì 7 febbraio 2011 alle 07:49 | Pubblicato su Diario, Installation and Configuration, Performance Tuning, Varie | Lascia un commento
Tag: , ,

Nel giro di pochi mesi mi sono trovato ad analizzare stranissimi comportamenti di Oracle in esecuzione di query, con pericolosi errori nei risultati.  La prima volta che mi è capitato è stato su una istanza 10.1.0.3 32 bit su Windows,  in tale occasione si trattava di una macchina di sviluppo e potei fare un po’ di analisi che però non mi diedero grande aiuto. In quell’occasione la creazione di un indice specifico, comunque necessario, faceva si che la query restituisse un risultato corretto; risolto così il problema specifico lasciai un po’ perdere, nel frattempo la macchina è stata sostituita e così ho perso anche i trace che feci a suo tempo.

Poche settimane fa mi è stato sottoposto un problema analogo, questa volta però su un database di produzione, 10.1.0.5 64 bit su HP-UX.

Il problema mi è stato sottoposto da un collega che stava facendo delle indagini sui dati e che casualmente si era accorto che sostituiendo un criterio di ricerca (nella clausola WHERE) con un’altro equivalente (ma basato sulla descrizione in una tabella di decodifica anziché sull’ID numerico) i risultati della query cambiavano, erroneamente. Riporto i due casi test:


select ANAG1MATRICOLA
from ANAGRAFICA1 , ANAGRAFICA2 , DECODIFICA1
where ANAG1ID_ANAG2=ANAG2ID
and ANAG1ID_DECOD1=DECOD1ID
and ANAG1VISIBILE = '1'
and DECOD1DESCRIZIONE = 'CC-SMMAN'

0 RECORD

-------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                |       |       |  7419 (100)|          |
|   1 |  NESTED LOOPS                  |                | 17482 |   699K|  7419   (4)| 00:00:08 |
|   2 |   MERGE JOIN                   |                | 34949 |  1262K|  7202   (1)| 00:00:08 |
|   3 |    SORT JOIN                   |                |  1446K|    34M|  7199   (1)| 00:00:08 |
|*  4 |     TABLE ACCESS BY INDEX ROWID| ANAGRAFICA1    |  1446K|    34M|  7199   (1)| 00:00:08 |
|   5 |      INDEX FULL SCAN           | IDXANAG1_11     |  8408 |       |    22   (5)| 00:00:01 |
|*  6 |    SORT JOIN                   |                |     1 |    12 |     3  (34)| 00:00:01 |
|   7 |     TABLE ACCESS BY INDEX ROWID| DECODIFICA1    |     1 |    12 |     2   (0)| 00:00:01 |
|*  8 |      INDEX RANGE SCAN          | IDXDECOD101    |     1 |       |     1   (0)| 00:00:01 |
|*  9 |   INDEX UNIQUE SCAN            | IDXANAG2       |     1 |     4 |     0   (0)|          |
-------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

 4 - filter("ANAG1VISIBILE"='1')
 6 - access("ANAG1ID_DECOD1"="DECOD1ID")
 filter("ANAG1ID_DECOD1"="DECOD1ID")
 8 - access("DECOD1DESCRIZIONE"='CC-SMMAN')
 9 - access("ANAG1ID_ANAG2"="ANAG2ID")



select ANAG1MATRICOLA
from ANAGRAFICA1 , ANAGRAFICA2 , DECODIFICA1
where ANAG1ID_ANAG2=ANAG2ID
and ANAG1ID_DECOD1=DECOD1ID
and ANAG1VISIBILE = '1'
and DECOD1ID = 18

357 RECORD

------------------------------------------------------------------------------------
| Id  | Operation           | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |              |       |       | 14319 (100)|          |
|*  1 |  HASH JOIN          |              |   481 | 15392 | 14318  (19)| 00:00:14 |
|   2 |   NESTED LOOPS      |              |   141 |   987 |     1   (0)| 00:00:01 |
|*  3 |    INDEX UNIQUE SCAN| IDXDECOD1    |     1 |     3 |     0   (0)|          |
|   4 |    INDEX FULL SCAN  | IDXANAG2     |   141 |   564 |     1   (0)| 00:00:01 |
|*  5 |   TABLE ACCESS FULL | ANAGRAFICA1  |   961 | 24025 | 14317  (19)| 00:00:14 |
------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

 1 - access("ANAG1ID_ANAG2"="ANAG2ID")
 3 - access("DECOD1ID"=18)
 5 - filter(("ANAG1ID_DECOD1"=18 AND "ANAG1VISIBILE"='1'))


TABLE_NAME                     NUM_ROWS
------------------------------ ----------------------
ANAGRAFICA2                     141
ANAGRAFICA1                     1732607
DECODIFICA1                     86

 

 

Nel primo caso la ricerca per descrizione (DECOD1DESCRIZIONE = ‘CC-SMMAN’) dava un risultato sbagliato di 0 record, nel secondo caso, andando per ID il risultato era di 357 record correttamente. Il motivo sta nel piano di esecuzione e più precisamente nel fatto che nel primo caso Oracle si ostina a usare un indice (IDXANAG1_11) che è su un campo che in questa neppure compare e che soprattutto, come si può ricavare anche dal piano sopra riportato ha valori non nulli per soli 8408 record sugli oltre 1,7 milioni presenti in quella tabella (ANAGRAFICA1).

Essendo un ambiente di produzione non possibilità di fare test “invasivi” come feci a suo tempo sul database di sviluppo, in quel caso provai a rimuovere e ricreare l’indice “sbagliato” e oracle insisteva ad utilizzarlo, esportai le tabelle e le reimportai sullo stesso database su uno schema a parte e l’errore non si ripresentava. Di mezzo, allora come oggi c’è un MERGE JOIN e sul forum di Oracle DBA Italia, dove ho sottoposto il mio problema mi è stato indicato  il bug 5921386 che calza abbastanza, anche se li si parla di MERGE JOIN OUTER e il mio è un MERGE JOIN normale, però a un certo punto nella nota oracle compare: “full index scan with potenal of  NULL value used inouter join” che è ciò che ho osservato io nel mio caso.

Hint SQL che forzano un piano di esecuzione di verso (tipo NO_USE_MERGE, o INDEX su altri indici della tabella ANAGRAFICA1) funzionano, rimane però una grossa e pericolosa falle nel CBO di oracle 10.1.05.

Pagina successiva »

Blog su WordPress.com.
Entries e commenti feeds.