Flash cache, exadata et 11GR2

Beaucoup de nouveautés avec la 11GR2 ! L’utilisation de mémoire flash en cache est une des innovations importantes apportée par cette version, mais  il reste difficile de faire la synthèse des informations qui circulent sur l’utilisation de la technologie mémoire flash.
Jetons un oeil avisé et détaillé à tout cela … et je vais vous fournir quelques pointeurs très intéressant sur le sujet

EXADATA V2 et FLASH CARD

La première fois que l’on a entendu parler de  l’utilisation de flash cache en liaison avec la base de données c’était  lors de la présentation de l’Exadata V2 au grand show de San Fransisco en octobre dernier. Oracle à intégré dans le module Exadata Sorage Server, qui sert de contrôleur intelligent  aux unités de stockage,  quatre cartes flash PCI de 96Go chacune.  Ces cartes, de référence « Sun Flash Accelerator F20« , ont des performances impressionnantes et sont  de type SSD à mémoire SLC.
Deux utilisations sont possibles pour ces ‘400Go’ :

  • Soit ils sont utilisés par le contrôleur comme un cache intelligent et  c’est le logiciel intégré qui décide quels sont les blocs qui  seront cachés ou non, tout en évitant de conserver  des informations inutiles, comme les blocs manipulés pendant les sauvegardes ou ceux des opérations de ré-équilibrage, et en laissant à l’utilisateur l’option de forcer la mise en cache de tables particulières.
  • Soit ils peuvent être configurés comme des disques classiques et intégrés via ASM dans des groupes de disques, il n’y alors plus de notion de cache mais on profite pleinement des performances de ce type de mémoire.

Dans les deux cas et pour l’usage de ces cartes flash du module Exadata Storage Server, comme le précise Kevin Closson dans son premier article le sujet, il n’y a aucun lien avec la SGA et le cache des données des instances. Cet article est d’ailleurs une mine d’informations, je vous en recommande la lecture ainsi que celle de ses références et  de la seconde partie.
D’autres informations à suivre dès que j’aurais eut le loisir de manipuler ce type de matériel (ce qui ne vas pas tarder).

DATABASE FLASH CACHE

L’autre possibilité d’utilisation d’une mémoire flash avec la base de données est apparue elle aussi avec la version 11GR2 sous la forme de la fonctionnalité Database Smart Flash Cache et des deux paramètres associés db_flash_cache_file et db_flash_cache_size.
Elle  permet de disposer d’un cache de niveau 2 pour le cache des données, donc d’une extension de la SGA sur une nouvelle zone d’accès, normalement beaucoup plus rapide que les disques classiques.

Prérequis

Pour disposer de cette fonctionnalité, il faut utiliser un système d’exploitation Linux certifié, la version 11.2.0.1 du logiciel de base de données et surtout le patch 8974084 (disponible uniquement ce jour  pour x86 et x86-64, il faudra patienter encore un peu pour les autres distributions).
Sans ce correctif, il est  impossible de définir correctement le paramètre db_flash_cache_file, bien que celui ci soit présent.
Une commande de type

alter system set db_flash_cache_file   = '/media/disk/flash.dat'  scope =spfile ;

nous retourne une erreur « ORA-32005 error while parsing size specification … »

Testons un peu …

Comme Guy Harrison sur son blog, je me suis livré à quelques tests simples sur mon laptop avec une petite clé USB  de 64MO sur un environnement OEL5  sous VMware, il n’est donc pas question de parler de performances mais seulement de fonctionnalités.
La mise en œuvre est directe:
Création d’un fichier de 64Mo sous l’arborescence de la clé USB qui est visible sous /media/disk et le faire appartenir à l’ utilisateur oracle.

#dd if=/dev/zero of=/media/disk/flash.dat bs=1M count=64
#chown oracle:dba /media/disk/flash.dat

Positionnement  des deux variables:

$sqlplus / as sysdba
SQL> alter system set db_flash_cache_file='/media/disk/flash.dat' scope=spfile;
SQL> alter system set db_flash_cache_size=64M scope=spfile ;

On peut constater avant de stopper puis de relancer la base que les statistiques associées à l’utilisation du flash cache sont présentes mais toutes à 0 :

SQL> select name,value from v$sysstat where name like '%flash cache%' ;
physical read flash cache hits                                     0
flash cache inserts                                                0
flash cache eviction: invalidated                                  0
flash cache eviction: buffer pinned                                0
flash cache eviction: aged out                                     0
flash cache insert skip: not current                               0
flash cache insert skip: DBWR overloaded                           0
flash cache insert skip: exists                                    0
flash cache insert skip: not useful                                0
flash cache insert skip: modification                              0
flash cache insert skip: corrupt                                   0

Les paramètres ne sont pas dynamiques, il est donc nécessaire de bouncer l’instance de la base de données pour qu’ils soient pris en compte.
Après le redémarrage, on constate tout de suite (certainement à cause de certaines options de sécurité en place dans ma base) la valorisation de certaines des statistiques :

SQL> select name,value from v$sysstat where name like '%flash cache%' ;
physical read flash cache hits                                    24
flash cache inserts                                             1987
flash cache eviction: invalidated                                  2
flash cache eviction: buffer pinned                                0
flash cache eviction: aged out                                     0
flash cache insert skip: not current                               0
flash cache insert skip: DBWR overladed                          965
flash cache insert skip: exists                                    0
flash cache insert skip: not useful                                2
flash cache insert skip: modification                              1
flash cache insert skip: corrupt                                   0

Quelques ordres SELECT simple sur le dictionnaire augmentent encore le nombre de ‘physical read flash cache hits’  ainsi que les insertions de blocs dans le flash cache (flash cache insert) :

SQL> select count(*) from dba_objects ;
73271
SQL> select count(*) from dba_tables ;
2842
SQL> select name,value from v$sysstat where name like '%flash cache%' ;
physical read flash cache hits                                     540
flash cache inserts                                               2637
flash cache eviction: invalidated                                    2
flash cache eviction: buffer pinned                                  0
flash cache eviction: aged out                                       0
flash cache insert skip: not current                                 0
flash cache insert skip: DBWR overl                                965
flash cache insert skip: exists                                    364
flash cache insert skip: not useful                                 57
flash cache insert skip: modification                                1
flash cache insert skip: corrupt                                     0

Il existe un nouveau statut nommé ‘flashcur‘  pour les blocs présents dans le cache et visibles au travers de la vue v$bh,
on peut donc retrouver les objets les plus concernés et leur répartition par la requête suivante :

select owner ||'.'|| object_name object,
sum (case when b.status like 'flash%' then 1 end) flash_blocks,
sum (case when b.status like 'flash%' then 0 else 1 end) cache_blocks,
count(*) total_cached_blocks
from v$bh b join dba_objects o
on (objd = object_id)
group by owner,object_name
order by 4 asc
/

Ce qui a donné dans mon cas le résultat suivant (affichage des premières lignes):

OBJECT                     FLASH_BLOCKS    CACHE_BLOCKS          TOTAL_CACHED_BLOCKS
-------------------------------------------------------------------------------------
SYS.C_FILE#_BLOCK#                  17              304                          321
SYS.C_OBJ#_INTCOL#                 203              306                          509
XDB.XDB$RESOURCE                   510              181                          691
SYS.I_OBJ2                                          750                          750
SYS.OBJ$                                            911                          911
SYS.IDL_UB1$                       479              491                          970
SYS.C_OBJ#                         546             1380                         1926
SYS.C_TOID_VERSION#                                2860                         2860

Comme le remarque et l’explique Guy Harrison dans son billet suivant « More on the Database Cache‘, la responsabilité de mettre les blocs dans le flash cache est laissé au processus DBWR .
On peut le vérifier en réalisant une insertion d’1 Million de lignes par une boucle dans une table T_EMP (clone de la table HR.EMPLOYEES) , boucle simple de la forme :

CONNECT HR/HR
BEGIN
FOR I IN 1 .. 100000
INSERT INTO T_EMP SELECT * FROM EMPLOYES;
COMMIT;
END LOOP;
END;
/

La table est constituée au finale de 11120 blocs (pour 1071712 lignes)  , OBJECT_ID récupéré depuis USER_OBJECTS,  la requête suivante à permis de voir la répartition entre le cache des données et le flash cache :

select b.status, count(b.status) from v$bh b join dba_objects o on (objd=object_id)
where o.owner='HR' and o.object_id=75599
group by b.status
/
STATUS     COUNT(B.STATUS)
---------- ---------------
xcur                  4298
flashcur              7700

Donc 7700 blocs dans le flash cache mise à la disposition potentielle des autres utilisateurs  par DBWR (seul process impliqué)  ,  évitant de futures lectures disques.
Guy Harrison fait dans son article un certains nombre d’assertions qui paraissent fondées, il nous fournit aussi deux requêtes pertinentes que je n’hésiterai pas à tester lorsque j’aurai l’architecture adéquate à disposition. Sa conclusion sur l’efficacité de la solution est intéressante et il est évident que la qualité et le type d’architecture des cartes flash utilisées sera primordiale (retour au choix de la carte SUN précédemment citée). Quant à la saturation du processus DBWR, j’ai confiance en l’investissement d’Oracle pour que l’algorithme s’améliore rapidement et que ce point de contention disparaisse.

Compléments

Avant de terminer , quelques points de détails que j’ai constaté dans l’utilisation de la fonctionnalité:

  • Une fois le flash cache défini , il n’est pas possible de modifier dynamiquement sa taille, cela déclenche des erreurs :
SQL> show parameter flash
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_flash_cache_file                  string      /tmp/flashtmp.dat
db_flash_cache_size                  big integer 64M
db_flashback_retention_target        integer     1440
SQL> alter system set db_flash_cache_size=50M scope=memory ;
alter system set db_flash_cache_size=50M scope=memory
*
ERROR at line 1:
ORA-02097: parameter cannot be modified because specified value is invalid
ORA-12427: invalid input value for db_flash_cache_size parameter

Et le message suivant dans le fichier journal  de la base :

Dynamic resize for flash cache is not supported now
(ori 67108864, new 52428800)
  • la mise à zéro de la valeur invalide l’utilisation du flash cache avec la trace suivante dans le fichier journal :
Disabling flash cache db_flash_cache_file (/tmp/flashtmp.dat)..
2009-12-21 15:14:22.161000 +01:00
L2 cache file closed by dbwr 0
L2 cache disabled for dbwr 0
ALTER SYSTEM SET db_flash_cache_size='0' SCOPE=MEMORY;
  • Il est impossible de refaire une validation dynamique avec une valeur de taille différente de la valeur initiale :
SQL> alter system set db_flash_cache_size=50M scope=memory ;
alter system set db_flash_cache_size=50M scope=memory
*
ERROR at line 1:
ORA-02097: parameter cannot be modified because specified value is invalid
ORA-12427: invalid input value for db_flash_cache_size parameter

Trace dans le fichier journal :

Dynamically re-enabling flash to a different size is not supported now
(ori 67108864, new 52428800)
  • Par contre, la remise en place de la valeur initiale valide de nouveau l’utilisation du flash cache :
Dynamically re-enabling flash cache db_flash_cache_file (/tmp/flashtmp.dat)
to size 67108864
ALTER SYSTEM SET db_flash_cache_size='64M' SCOPE=MEMORY;

Enfin,  pour tester la fonctionnalité, la création d’un fichier dédié au flash cache sur n’importe quel unité de disque suffit, il n’est pas nécessaire de posséder une carte flash (cela reste cependant d’un intérêt très limité et sera réservé uniquement à des tests).
J’espère que ces quelques lignes et les articles qui s’y rattachent vous ont intéressé, n’hésiter pas à réagir et/ou préciser d’autres liens intéressant sur le sujet.
En attendant, meilleurs vœux pour cette année 2010.