Rechercher sur arkzoyd.com

23 mars 2009

ASMLib et Device Mapper Multipath

My Oracle Support (Metalink) a parfois quelques paradoxes qui font sourire; la configuration d'ASMLib avec le Device Mapper sous Linux fait parti de ceux-ci, voici quelques extraits choisis qui vous aideront à comprendre de quoi je parle:
  • 602952.1 - How To Setup ASM & ASMLIB On Native Linux Multipath Mapper disks?
Keep in mind for ASMLIB disks you will need to use the /dev/dm-* disks instead of the /dev/mapper/mpath* devices since they are present in the partition table ==)> /proc/partitions and ASMLIB will look at that file during the disk discovering phase. If you do not use the disks located at /dev/dm-* then ASM will not be able to discover them.
  • 357472.1 Configuring device-mapper for CRS/ASM
the /dev/dm-N devices are internal to device mapper and should never be used.
These devices are not persistent. Starting with Red Hat Enterprise Linux 5, these devices are no longer created by udev.
/dev/dm ou pas /dev/dm? Si l'argument de la seconde note semble imparable, celui de la première semble vraisemblable. J'ai donc vérifié dans le code source que vous pouvez récupérer sur le site d'Oracle et il apparaît en effet que le premier argument est vrai aussi ! scan-partitions.c recherche bien les partitions dans /proc/partitions.

Alors qui croire ? Et bien en fait peu importe ! ASMLib stocke le nom du device à aucun endroit. Au lieu de cela:
  • tout est stocké dans les entêtes des disques et ne font référence à aucun device,
  • les devices sont scannés au démarrage du service ASM ou lorsque vous exécutez la commande scandisk en fonction des paramètres ORACLEASM_SCANORDER et ORACLEASM_SCANEXCLUDE de /etc/sysconfig/oracleasm,
  • lorsque les devices sont trouvés, ASMLib crée un device avec le couple [major,minor] correspondant dans /dev/oracleasm/disks. Ce device a le nom du disque créé avec createdisk.
Tant et si bien que pour retrouver quel device correspond à quel un disque ASM, vous pouvez regarder le couple [major,minor] et le comparer à celui des autres devices du serveur comme ci-dessous:
ls -l /dev/oracleasm/disks

# Si vous utilisez DM:
ls -l /dev/mapper

# Si vous utilisez un device simple
ls -l /dev
Pour en savoir plus, quelques documents à lire absolument:

21 mars 2009

Changer la destination des archivelogs automatiquement

C'est plutôt étonnant mais on trouve peu d'informations sur l'utilisation de la clause alternate avec location dans log_archive_dest_n. Pourtant, il est possible d'avoir une destination distante, sur NFS par exemple, et que, si celle-ci n'est plus disponible, les archivelogs soient stockés localement.

Pour tout dire, il vaut mieux stocker les archivelogs sur les 2 destinations, locale et distante quitte à permettre à votre base de données de continuer à opérer si une destination échoue et à superviser le bon fonctionnement des 2 destinations. C'est sans doute pour cette raison que les différentes sources d'informations sont avares de description du cas précédent. Enfin, j'ai d'autres cas d'utilisation en tête, alors voici un exemple d'une configuration qui change de destination automatiquement en cas d'indisponibilité de la première destination:
alter session set log_archive_dest_1='location=/nfsmount/db/arch -
mandatory reopen=0 alternate=log_archive_dest_2';

alter session set log_archive_dest_state_1=enable;

alter session set log_archive_dest_2='location=/local/db/arch';

alter session set log_archive_dest_state_2=alternate;
Vous noterez que la première destination est un sous répertoire du point de montage de sorte que le process d'archive échoue si cette destination n'est plus accessible.
Une fois que l'environnement a basculé de la première à sa seconde destination, elle ne revient pas automatiquement en arrière; Il faut règler le problème manuellement, en exécutant, par exemple, le script ci-dessous:
alter session set log_archive_dest_state_1=enable;

alter session set log_archive_dest_state_2=alternate;
Et il faudra aussi ré-acheminer les archivelogs sur le stockage distant et le re-enregistrer dans le catalogue ou le controlfile. Je me demande si ça fonctionne avec une version Standard Edition ou Standard-One ?

20 mars 2009

La vérité sur la commande "RENAME"

La commande rename que vos trouverez dans Oracle 11g SQL Reference n'est pas votre amie ! Pourtant si vous lisez les restrictions de la documentation, vous trouverez, simplement:
Renaming objects is subject to the following restrictions:
  • You cannot rename a public synonym. Instead, drop the public synonym and then re-create the public synonym with the new name.
  • You cannot rename a type synonym that has any dependent tables or dependent valid user-defined object types.
Alors pourquoi faut-il lui préferer alter table mytable rename pour renommer une table? La première réponse vient avec un rapide test:
rename scott.emp to emp2;
*
ERROR at line 1:
ORA-01765: specifying table's owner name is not allowed
Et non! Vous ne pouvez pas préciser le nom du schéma de l'objet que vous voulez renommer; mais vous me direz qu'il y a plusieurs moyens de contourner cette limite; alors voici une seconde raison que vous trouverez dans la section "Types of DDL Changes Ignored by an Apply Process" de la documentation: Si vous utilisez Oracle Streams, vous ne pourrez pas répliquer cette commande. Ou du moins pas sans vous faire un noeud au cerveau!

Mais pourquoi donc? Et bien pour une troisième raison qui n'est pas documentée celle-ci: Vous ne pouvez pas utiliser la commande rename après avoir exécuté alter session set current_schema=...; la preuve:
alter session set current_schema=scott;

rename emp to emp2;
*
ERROR at line 1:
ORA-03001: unimplemented feature
Et oui, rename n'est pas implémenté dans ce contexte; cela explique sans doute pourquoi les process d'apply ne sont pas capables de l'appliquer. Mais, et ça sera la conclusion de ce post, à moins que vous n'ayez une bonne raison pour ne pas utiliser alter table ... rename to ... (et je ne vois pas laquelle !), préférez toujours cette dernière syntaxe au rename: ça évitera quelques soucis à celui ou celle qui passera après vous. A moins, bien sur, que vous ne fassiez tout ça que pour ça...

19 mars 2009

Afficher un texte formaté dans un script...

Avez-vous remarqué? Lorsque vous passez un espace ou une ligne avec dbms_output et set serveroutput on dans SQL*Plus, celui-ci n'obeit pas avec zèle:
set serveroutput on

begin
dbms_output.put_line('Ligne sans espace');
dbms_output.put_line('> Ligne avec espaces et 1er caractere');
dbms_output.put_line(' Ligne avec espaces, sans 1er caractere');
dbms_output.new_line;
dbms_output.put_line('nouvelle ligne');
end;
/

Ligne sans espace
> Ligne avec espaces et 1er caractere
Ligne avec espaces, sans 1er caractere
nouvelle ligne
Et bien... la faute au format d'affichage par défaut de SQL*Plus qui gère les espaces intelligemment:
show serveroutput

serveroutput ON SIZE UNLIMITED FORMAT WORD_WRAPPED
Si vous revenez à un format d'affichage moins intelligent, vous pourrez passez des lignes selon vos envies:
set serveroutput on format trun

show serveroutput
serveroutput ON SIZE UNLIMITED FORMAT TRUNCATED

begin
dbms_output.put_line('Ligne sans espace');
dbms_output.put_line('> Ligne avec espaces et 1er caractere');
dbms_output.put_line(' Ligne avec espaces, sans 1er caractere');
dbms_output.new_line;
dbms_output.put_line('nouvelle ligne');
end;
/

Ligne sans espace
> Ligne avec espaces et 1er caractere
Ligne avec espaces, sans 1er caractere

nouvelle ligne
Me voilà redevenu maitre de mes espaces!

15 mars 2009

Quels sont les derniers RPM installés sur RHEL ou OEL?

L'histoire montre qu'il peut être utile de savoir quels sont les RPM récemment installés. L'option --last de la commande rpm ne semble pas faire bon ménage avec --queryformat; vérifier si la version installée récemment est 32 ou 64 bits sur x86_64 peut donc ne pas être si simple! Testez par vous-même:
rpm -qa --last
Voici une solution alternative:
rpm -qa --queryformat \
'%{installtime} %{installtime:date}: %{NAME}-%{VERSION}-%{RELEASE} (%{ARCH}) \n' | \
sort -n |cut -d ' ' -f "2-"

12 mars 2009

Un repository YUM public pour RHEL et OEL?

Twitter laisse supposer qu'Oracle pourrait faire un pas de plus pour faciliter l'utilisation d'Oracle Enterprise Linux (OEL). Ils publieraient un repository YUM public pour permettre les mises à jour d'OEL et de RHEL d'ici peu. Ça simplifierait pour beaucoup l'installation et la validation des pré-requis, et ce, même si vous n'avez pas de contrat support avec RHEL ou OEL! J'utilise le conditionnel puisque l'URL http://public-yum.oracle.com n'est pas encore disponible, ni d'ailleurs les conditions d'utilisation ou le détail du contenu du repository...

Dans la même veine, vous trouverez également un intéressant article à propos de la stratégie et des motivations derrière Unbreakable Linux.

09 mars 2009

Comment répliquer une table entre Oracle et MySQL avec Oracle Streams ? (Partie 1)

J'ai cherché une idée pour partager mes 3 blogs à travers le même sujet... Le voici: "Comment répliquer une table entre Oracle et MySQL avec Streams ?". Ce que je propose, c'est donc d'aborder dans l'ordre:
Si vous êtes intéressé par l'un ou l'autre de ces blogs, vous pouvez vous abonner. Voici les liens correspondants pour mon blog en français, pour mes posts en anglais sur le site de The Pythian Group (et ici pour les posts de tout The Pythian Group) et enfin pour We Do Streams!

Installer MySQL sur Ubuntu

Les bonnes nouvelles d'abord ! Ce que j'aime dans Ubuntu, c'est que mon fils de 9 ans peut s'en servir dans 95% des cas... Installer MySQL 5.0 sur Intrepid Ibex ou Hardy Heron n'est donc pas plus compliqué que la commande ci-dessous (ou la selection des package dans Synaptic Package Manager) :
sudo apt-get install mysql-server mysql-client
Et voilà, l'outil vous posera une unique question qui est le mot de passe de l'utilisateur root de mysql. J'ai mis manager, histoire de ne pas perdre le lien qui m'unit avec Oracle et me voilà avec MySQL 5.0 sur Intrepid!

Créer une base de données, un utilisateur, une table, une ligne

L'étape suivante consiste à:
  • Se connecter:
mysql -uroot -pmanager
  • Créer une base de données demo; Pour des raisons d'incompatibilité de la gateway ODBC d'Oracle avec MySQL utf8, on choisira le jeu de caractènres par défaut pour la base latin1 :
create database demo character set latin1;
  • Créer un utilisateur demo (mot de passe: demo) et lui donner un accès complet la nouvelle base de données:
grant all privileges on demo.* to 'demo'@'localhost'
identified by 'demo' with grant option;

flush privileges;
  • Se connecter avec le nouvel utilisateur:
exit;

# mysql -?
mysql -udemo -pdemo -Ddemo
  • Créer une table avec différent types de données avec InnoDB:
create table demo (
col1 integer,
col2 date,
col3 varchar(10),
col4 varchar(10) character set utf8,
col5 varbinary(10)) engine innodb;
  • Insérer une ligne dans la table:
insert into demo(col1, col2, col3, col4, col5)
values(1, cast(now() as date), '0123456789', '0123456789', '0123456789');

select * from demo \G

*********** 1. row ************
col1: 1
col2: 2009-03-11
col3: 0123456789
col4: 0123456789
col5: 0123456789
Installer MySQL Connector ODBC 5.1

Cette partie contient quelques pièges : (1) La gateway générique d'Oracle ne fonctionne pas avec le driver 3.51 parce que celui-ci n'implémente pas SQLSetDescRec (cf bug 32692); (2) il n'existe pas de package pour le connector ODBC 5.1 et il faut donc l'installer depuis les sources; (3) le connector ODBC 5.1 ne fonctionne pas avec la version iodbc de Ubuntu Hardy et Intrepid.

Il faut donc installer le connector manuellement depuis les sources et tester depuis un autre outils que iodbctest... Dans l'ordre, il faut :
tar -zxvf mysql-connector-odbc-5.1*.tar.gz
cd mysql-connector-odbc-5.1*
  • Installer les packages nécessaires pour compiler le connector; la liste n'est peut-être pas exhaustive et vous la compléterez :
sudo apt-get install unixODBC unixODBC-dev \
libmysqlclient15-dev iodbc \
libqt3-mt libqt3-headers
  • Configurer le source pour votre environnement et en particulier:
    • --prefix pour indiquer le répertoire qui contiendra le connector ODBC
    • --with-qt-includes pour indiquer l'emplacement des headers qt3
./configure --prefix=/home/oracle/myodbc51 \
--with-qt-includes=/usr/include/qt3
aclocal
autoheader
autoconf
automake
make
  • Déployer le connector dans le répertoire d'installation:
make install
Configurer la source de données ODBC

Vous pouvez utiliser iodbcadm-gtk pour configurer la source de données. Enregistrez le driver ODBC; mettez le fichier libmyodbc5.so dans "Driver file name" et libmyodbc3S.so dans "Setup file name"; Un fichier .odbcinst.ini est créé dans le répertoire $HOME:
cd ~
$ cat .odbcinst.ini
[ODBC Drivers]
MySQL ODBC Driver 5.1 = Installed

[MySQL ODBC Driver 5.1]
Driver = /home/oracle/myodbc51/lib/libmyodbc5.so
Setup = /home/oracle/myodbc51/lib/libmyodbc3S.so
Vous pouvez ensuite créer un DSN user; Il est stocké dans le fichier .odbc.ini du répertoire $HOME:
cd ~
$ cat .odbc.ini
[ODBC Data Sources]
demo = MySQL ODBC Driver 5.1

[demo]
Driver = /home/oracle/myodbc51/lib/libmyodbc5.so
DATABASE = demo
DESCRIPTION = MySQL ODBC 5.1.5 Connector Sample
PORT = 3306
SERVER = 127.0.0.1
CHARSET = latin1
UID = demo
PWD = demo
TRACEFILE = /tmp/myodbc51.trc
TRACE = OFF
Important:
Pour utilisez avec Oracle, vous devez utiliser une variable CHARSET qui ne soit pas utf8; latin1 fera l'affaire comme nous le verrons

Tester la source de données


Si vous utilisez iodbc pour tester la source de données, vous obtenez un message d'erreur incompréhensible, comme ci-dessous:
iodbctest DSN=demo
iODBC Demonstration program
This program shows an interactive SQL processor
Driver Manager: 03.52.0607.1008
1: SQLDriverConnect = ������������������� (0) SQLSTATE=
1: ODBC_Connect = �������������������� (0) SQLSTATE=
Mais le driver fonctionne très bien; si vous voulez tester, utilisez odbctest, sans le "i" de unixODBC! Cela étant plus simple reste d'utiliser "OpenOffice.org Database" et de sélectionner "Connect to an existing database" -> ODBC pour se connecter à MySQL via ODBC.

Voilà. A bientôt sur le blog de The Pythian Group pour configurer la gateway Oracle et accéder à MySQL depuis SQL*Plus. Je commenterai ce post une fois mon prochain post disponible.

07 mars 2009

Ubuntu et sqlpython

Catherine Devlin qui a repris le flambeau de sqlpython a introduit il y a quelques jours, une fonctionnalité juste pour moi, semble-t-il! La possibilité d'utiliser le caractère "*" dans le nom d'une colonne d'un select. C'est super si vous connaissez, seulement à peu prêt, le nom d'une colonne, comme c'est souvent mon cas. En plus sqlpython permet d'afficher les lignes en colonnes en remplaçant select par tselect.

J'ai donc décidé d'installer sqlpython sur mon Laptop Ubuntu; une vrai partie de plaisir! Il faut d'abord installer python, python-setuptools et python-dev:
sudo -s

apt-get install python python-setuptools python-dev
Ensuite, positionnez l'environnement Oracle et installer cx_Oracle:
. oraenv
BLACK

sudo -E easy_install cx_Oracle
Enfin sqlpython avec l'une ou l'autre des syntaxes qui suivent:
sudo -E easy_install sqlpython

sudo -E easy_install \
http://pypi.python.org/packages/source/s/sqlpython/sqlpython-1.6.0.tar.gz
3 minutes plus tard, vous pouvez utiliser ces 2 fonctionnalités dont on peut se demander pourquoi se n'est pas encore dans SQL*Plus:
sqlpython system/manager@black
/usr/bin/gedit

MySqlPy V1.6.0 - 'sqlplus in python'
Author: Luca.Canali@cern.ch
Rev: 1.6.0, 02-Mar-09

[...]

system@black> set wild on
wildsql - was: False
now: True

system@black> tselect *mode from v$database;


COLUMN NAME ROW N.1
--------------- -------------------
LOG_MODE ARCHIVELOG
OPEN_MODE READ WRITE
PROTECTION_MODE MAXIMUM PERFORMANCE

06 mars 2009

Sauvegardes Oracle Tout Court

Je ne sais pas si vous avez remarqué... Tous les DBA savent mettre en place une sauvegarde mais dès qu'il s'agit de restaurer un environnement critique parce qu'un "Qsxg@34Bbv~", heureusement d'une autre équipe, a mis le SAN en compote et que le-dit environnement est "highly critical", il n'y a plus que deux ou trois personnes pour se retrousser les manches. Bizarrement, même quand le problème commence à minuit, je me retrouve dans l'histoire. Heureusement que j'ai des copains en Australie... Merci les kangourous!

Ce message s'adresse donc aux "Qsxg@34Bbv~" et leurs responsables, aux DBA qui mettent en place des sauvegardes et sont bizarrement absents quand un problème arrive et aussi à VOUS et MOI, parce qu'on peut apprendre autant des erreurs des autres que des siennes...

Principes Fondamentaux
Comme dirait un bon copain : "C'est évident mais ça va mieux en le disant!".
Les consultants vous le diront: "Une sauvegarde fait partie d'une stratégie de sécurisation"
J'ai tendance à penser: "Une sauvegarde est une tactique qui s'inscrit dans un contexte!"
Mettre en place une sauvegarde inclut de tester qu'on peut la restaurer sur un AUTRE serveur : ça vous permettra de vous assurez que vous n'oubliez pas un fichier dans l'histoire et de vous assurer aussi que vous n'avez besoin de personne pour restaurer votre base de données. C'est particulièrement vrai avec les Media Managers dont les agents pour RMAN sont très intelligents; s'il ne sont pas correctement paramétrés ou/et que vous ne leur envoyez pas les bonnes informations, ils offrent une sécurité à toute épreuve : vous ne pourrez pas accéder aux sauvegardes. Soyez attentifs également si vous faites des sauvegardes depuis plusieurs noeuds d'un cluster. Si vous faites des sauvegardes incrémentales toute la semaine, faites vos tests un vendredi et pas un lundi; faites vos tests après au moins 10 jours et pas juste après une installation. Mais vous savez tout ça, alors faites-le! Plus tard ça sera trop tard!

J'entends déjà mes responsables, mes collègues ou mes clients se plaindre du prix d'un test. Et si vous avez 500 bases de données? Industrialiser/standardiser n'interdit pas de tester! Préférez-vous découvrirez tous vos problèmes le mauvais jour? Ca pourrait vous coutez bien plus cher, jusqu'à sonner le glas de votre entreprise. Si votre base est corrompue et que vous n'avez pas de sauvegardes valides, vous pourrez toujours appeler une superstar du support d'Oracle mais, même lui, pourrait ne pas avoir que des bonnes nouvelles pour vous! Et ça ne lui fera pas plus plaisir qu'à vous...

Autre évidence, mettre en place une sauvegarde, c'est aussi mettre en place sa supervision. Et par supervision, je N'entends PAS "valider que les scripts sont exécutés et ne retournent pas d'erreurs". J'entends s'assurer chaque jour que vous avez tout ce qu'il faut pour restaurer votre environnement. J'entends connaitre le temps qu'il vous faudra pour restaurer votre environnement pour chaque cas de panne. J'entends, valider que c'est conforme à vos engagements, votre SLA. J'entends évaluer les risques (et pas en % mais bien en € ou en $). Bien sur ce n'est pas facile! Mais (1) les professionnels le font et nous sommes des professionnels, (2) certains outils, en particulier Recovery Manager avec les commandes crosscheck, validate ou report vous aident et (3) c'est quand même plus intéressant que d'expliquer a posteriori pourquoi vous ou un autre s'est planté; surtout après s'être défoncé pendant 10 heures pour tout remettre d'équerre.

Enfin, on est tous, un jour, un "Qsxg@34Bbv~" ou le responsables d'un "Qsxg@34Bbv~" mais on peu essayer de l'être le moins souvent possible, au moins au travail. Il existe d'ailleurs des moyens de minimiser nos chances d'en être. Par exemple, aux US, par les temps qui courent, les "Qsxg@34Bbv~" et les responsables de "Qsxg@34Bbv~" ont une espérance de vie dans l'entreprise de l'ordre du LIO... Bien inférieure donc au temps qu'il m'a fallut pour revenir à la situation initiale. Inutile d'entrer dans le détail de la fin de l'histoire; j'ai ma médaille ça me suffit!

Principes Techniques

Ceci dit, il n'y a pas que des enseignements généraux que l'on peut tirer d'une situation comme celle-ci... Voici quelques considérations techniques:
  • Utilisez à dessein la commande RMAN "delete expired".
Imaginez le cas suivant: vous faites vos sauvegardes sur disque, dans une baies de stockage ou un filer séparé de votre production. Si pour une raison quelconque, y compris une maintenance planifiée pour appliquer un Firmware, vos fichiers de sauvegardes ne sont plus accessibles pendant que vous lancez une sauvegarde ou un script "cleanup", et vous faites, "crosscheck ...; delete expired ...;", vous supprimez toutes les références des fichiers dans le catalogue ou le fichier de contrôle. Lorsque les sauvegardes sont de nouveaux disponibles, ça risque d'être très compliqué de retrouver vos petits (*). D'autre part les fichiers étant supprimés du catalogue, si vous vous appuyez sur la policy RMAN pour supprimer vos fichiers, delete obsolete ne supprimera pas le fichier que restera "éternellement" sur votre disque.

Autrement dit, la commande crosscheck sert à détecter des problèmes dans les sauvegardes et la commande delete expired sert à supprimer des références dans le catalogue une fois qu'on a expliqué le problème. A moins que vous utilisiez une politique de rétention extérieure à RMAN, n'utilisez pas delete expired dans vos scripts.

(*) En fait sur disque la commande catalog start with ... de 10g vous rendra la tache facile mais retrouver les handler des fichiers dans le Media Manager pour les re-cataloguer avec la commande catalog device type 'SBT_TAPE' backuppiece 'Qsxg@34Bbv~'; pourrait bien devenir un petit cauchemar.
  • Par défaut un backup incrémental RMAN est différentiel... pas cumulatif!
C'est une idée faussement répandue... pour que votre incrémental soit cumulatif il faut en fait que vous utilisiez explicitement le mot clé cumulative. Autrement dit, si vous faite un incrémental "level 1" tous les jours et un "level 0" le dimanche, pour restaurer vendredi, vous devez appliquer 6 sauvegardes, non pas 2... A moins que vous n'utilisiez le mot clé cumulative.

Ceci amène une autre question qui est: "Comment déterminer le premier SCN d'un backup incrémental?". La meilleure réponse que j'ai trouvée pour l'instant est la colonne incremental_change# de la vue v$backup_datafile que vous pouvez comparer au checkpoint_change# de v$datafile_header; je vous laisse construire la requête! Si vous trouvez une commande RMAN pour afficher la même information, laissez un commentaire.
  • Attention aux fichiers offline!
Selon la manière dont un crash arrive, il se peut que certains fichiers passent offline avant que vos instances crashes. Il vous faudra donc les repasser online avant ou après avoir redémarrer votre base de données si, comme moi, vous repartez sur un current controlfile.

Dans le flot des erreurs, ce n'est pas toujours évident d'y pensez alors "Pensez-y!"

En outre, si le fichier fait partie du tablespace SYSTEM ou d'un UNDO, il est très probable que votre base refuse de démarrer. Si c'est votre cas, l'erreur n'est pas forcément très explicite; voici un exemple de message d'erreur lorsque vous essayez de redémarrer une base avec 1 fichier undo offline:
ORA-00704: bootstrap process failure
ORA-00604: error occurred at recursive SQL level 2
ORA-00376: file 5 cannot be read at this time
ORA-01110: data file 5: '+DATA/redx/datafile/undotbs3.17.68234245'
Error 704 happened during db open, shutting down database
USER (ospid: 7081): terminating the instance due to error 704
Ce qui peut vouloir dire "datafile 5 offline" ou pas...
  • Comment supprimer le membre d'un redo CURRENT ?
Si vous utilisez ASM et perdez le disk group qui contient un membre d'un redo log courant, vous ne pourrez pas copier un autre membre pour le remplacer, à moins que vous ne nommiez vos fichiers de redo logs avec des alias. En effet : vous ne pouvez pas copier un fichier et forcer son nom si ce nom est conforme à un format OMF. Vous vous retrouvez donc dans une situation ou vous n'avez pas tous les membres du redo log courant et dans l'impossibilité de supprimer le membre avec alter database drop logfile member ..., ni de changer de log courant avec alter system switch logfile;.

Et bien ce n'est pas grave! votre base de données pourra être ouverte sans tous les membres des redolog courant. En fait vous verrez des messages comme ci-dessous dans votre fichier alert.log et les membres seront automatiquement supprimés:
ORA-00313: open failed for members of log group 2 of thread 1
ORA-00312: online log 2 thread 1: '+DATA/redx/onlinelog/group_2.72.665161291'
ORA-17503: ksfdopn:2 Failed to open file +DATA/
redx/onlinelog/group_2.72.665161291
ORA-15012: ASM file '+DATA/
redx/onlinelog/group_2.72.665161291' does not exist
Une fois la base réouverte, il vous suffira de changer de redo log courant et d'ajouter le membre supprimé comme ci-dessous:
alter database add logfile member '+DATA' group 2;
  • Autre remarque
Les fichiers "temporaires" sont recréés automatiquement lors du redemarrage de la base de données. Je pensais que ce n'était que dans le cas d'un open resetlogs, ce que je n'ai pas fait(?). C'est peut-être parce que les fichiers sont OMF, ou une nouveauté de 11g... ou une fausse idée de ma part! Il faudrait bien que je teste ou que je cherche dans la documentation, un jour.

Conclusion

Si quelqu'un vous propose de gérer un ticket à minuit, demander lui pourquoi? Si vous voulez apprendre des trucs, prenez le ticket, sinon laissez-le à quelqu'un d'autre.

04 mars 2009

Récupérer l'outline d'un plan sans 10053...

Il me semble l'avoir déjà vu mais sans le retenir; Il existe des valeurs non documentées pour le paramètres format des fonctions pipeline disponibles dans DBMS_XPLAN. En particulier la valeur outline affiche l'ensemble des hints correspondant à l'outline du plan affiché. C'est beaucoup plus pratique que d'utiliser un event 10053 ou le create outline. Vous trouverez un exemple d'utilisation ci-dessous mais vous pouvez l'utiliser dans les autres fonctions de type display_*:
explain plan for select * from dual;

select * from table(dbms_xplan.display(null,null,'+outline'));

PLAN_TABLE_OUTPUT
--------------------------
Plan hash value: 272002086

[...]

Outline Data
-------------

/*+
BEGIN_OUTLINE_DATA
FULL(@"SEL$1" "DUAL"@"SEL$1")
OUTLINE_LEAF(@"SEL$1")
ALL_ROWS
OPTIMIZER_FEATURES_ENABLE('10.2.0.4')
IGNORE_OPTIM_EMBEDDED_HINTS
END_OUTLINE_DATA
*/

03 mars 2009

Comment vérifier un Critical Patch Update?

Les CPU (Critical Patch Update), comme les Patch Sets ou certains patchs unitaires nécessitent un ou plusieurs scripts SQL en plus de la mise à jour du logiciel; Voici comment vérifier que (1) le logiciel a été patché et que (2) les scripts correspondants ont été exécutés.

Pour vérifier la version d'Oracle ainsi que l'ensemble des patchs installés, utilisez Oracle opatch comme ci-dessous, après avoir positionné correctement la variable ORACLE_HOME :
cd $ORACLE_HOME/OPatch
./opatch lsinv -patch
Pour plus d'informations, utilisez l'option -detail :
./opatch lsinv -details
Les CPU sont des bundles de patchs et une liste des patchs unitaires apparait dans l'inventaire. Validez sur Metalink ou dans le CPU que ces patchs correspondent à ceux que vous voulez installer. Les dates du patch et d'installation peuvent être un outil intéressant; surtout vous utiliser un système de ticket.

Pour vérifier que les scripts correspondants aux patchs ont été exécutés, connectez-vous à votre base de données et exécutez la requête qui suit :
set lines 120
col action_time format a28
col comments format a50 wor wra
col version format a10

select action_time
, id
, version
, comments
from dba_registry_history
order by ACTION_TIME;

ACTION_TIME ID VERSION COMMENTS
---------------------------- ---------- ---------- ------------------------
03-MAR-09 09.53.52.370837 AM 10.2.0.4.0 Upgraded from 10.2.0.3.0
03-MAR-09 10.06.40.370930 AM 3 10.2.0.4 CPUJan2009
03-MAR-09 10.14.26.957691 AM 6452863 view recompilation
Une fois un CPU installé dans un ORACLE_HOME, il n'est pas utile de relancer le script catbundle.sql après créer une nouvelle base de données avec CREATE DATABASE ou avec DBCA "Custom Database". En revanche, vous devrez relancer les scripts si :
  • Vous utilisez un template de base de données avec DBCA
  • Vous utilisez un script DBCA créé avant l'application du CPU
  • Vous clonez, avec DBCA, une de base de données créée avant l'application du CPU
Pour plus de détails, se reporter au fichier README du CPUJan2009 et en particulier la section "3.3.5 Post Installation Instructions for New and Upgraded Databases"

Patcher Oracle GridControl de 10.2.0.4 a 10.2.0.5

Oracle Grid Control 10.2.0.5 est disponible sur Linux et Windows 32 bits sous le numéro ARU 3731593. Et voila... C'est installé sur la production de mon client californien! Beaucoup de nouveautés dans cette version; Les graphiques sont désormais en Flash et on trouve de nombreux écrans qui n'existant pas en 10.2.0.4 comme celui ci-dessous qui affiche l'activité des 8 instances d'un RAC sur une seule page (si vous avez Diagnostic Pack) :

Ou encore cet écran qui affiche les fonctionnalités MAA activées:
Ou encore la possibilité de désormais d'acquitter les alertes. Côté installation, il y a plusieurs choses à dire:
  1. D'abord les documents de référence:
    • 763072.1 Release Notes
    • 763088.1 List of Bug Fixes
    • Le patch 3731593
    • 412431.1 Oracle Enterprise Manager 10g Grid Control Certification Checker

  2. D'autre part, si comme moi, vous utilisez un port en dessous de 1024, comme 443 pour HTTPS, vous avez peut-être changé l'utilisateur et le groupe de .apatchctl. Si c'est le cas, changez le de nouveau pour le temps de la mise à jour; Assurez-vous également que EMKEY est stocké dans le référentiel.

  3. Je n'ai toujours pas trouvé les bonnes variables pour lancer runInstaller en mode silencieux; J'ai utilisé ORACLE_HOME, sl_pwdInfo={syspassword}, ACCEPT_LICENSE_AGREEMENT=false et METALINK_USERNAME="" mais l'installer a échoué avec le message ci-dessous:
    SEVERE: 3/3/09 10:49:57 AM GMT: Abnormal program termination. An internal error has occured. Please provide the following files to Oracle Support :
    "/usr/home/oracle/oraInventory/logs/installActions2009-03-03_10-49-54AM.log"
    "/usr/home/oracle/oraInventory/logs/oraInstall2009-03-03_10-49-54AM.err"
    "/usr/home/oracle/oraInventory/logs/oraInstall2009-03-03_10-49-54AM.out"
    Le fichier oraInstall2009-03-03_10-49-54AM.err contient:
    Exception java.lang.StringIndexOutOfBoundsException: String index out of range: 0 occurred..
    java.lang.StringIndexOutOfBoundsException: String index out of range: 0
    at java.lang.String.charAt(Unknown Source)
    at oracle.sysman.oii.oiio.oiioz.OiiozResponseFile.validateValue(OiiozResponseFile.java:562)
    at oracle.sysman.oii.oiis.OiisVariable.getValueFromCommandLine(OiisVariable.java:2605)
    at oracle.sysman.oii.oiis.OiisVariable.setVariable(OiisVariable.java:2184)
    at oracle.sysman.oii.oiis.OiisVariable.setVariable(OiisVariable.java:2124)
    at oracle.sysman.oii.oiic.OiicSessionContext.setVariables(OiicSessionContext.java:689)
    at oracle.sysman.oii.oiic.OiicInstallSession.initSession(OiicInstallSession.java:1206)
    at oracle.sysman.oii.oiic.OiicPullSession.initialize(OiicPullSession.java:1308)
    at oracle.sysman.oii.oiic.OiicSessionWrapper.initialize(OiicSessionWrapper.java:754)
    at oracle.sysman.oii.oiic.OiicSessionWrapper.initialize(OiicSessionWrapper.java:738)
    at oracle.sysman.oii.oiic.OiicInstaller.run(OiicInstaller.java:561)
    at oracle.sysman.oii.oiic.OiicInstaller.runInstaller(OiicInstaller.java:962)
    at oracle.sysman.oii.oiic.OiicInstaller.main(OiicInstaller.java:899)
    Impossible, dans mon cas d'utiliser un serveur X et donc d'enregistrer les variables dans un fichier avec "-record -destinationFile". Les mêmes variables dans un nouveau fichier de réponse fonctionne mais ne mettent pas à jour le referentiel. Comme pour 10.2.0.4, vous pouvez utiliser RepManager comme ci-dessous:
    ./RepManager -connect "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=myhost)
    (PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=EMREP)))" \
    -action upgrade -verbose -repos_user sysman
  4. Enfin, soyez patient... Pour la mise à jour du référentiel; Le chargement des fichiers XML avec transX prend une bonne heure.

02 mars 2009

Quelques News Oracle Technologies

De retour de vacances, ça m'a pris une partie de la matinée pour prendre connaissance de mes mails; des problèmes en suspend et me remettre dans le bain... Côté news "worth to mention" et qui concernent Oracle:
Sans oublier mes posts en anglais à propos d'Oracle Streams: