web-dev-qa-db-fra.com

Résolution de ORA-4031 "impossible d'allouer x octets de mémoire partagée"

J'ai besoin d'indications sur la façon de diagnostiquer et de résoudre ce problème. Je ne sais pas s'il s'agit d'un simple problème d'installation du serveur ou d'un problème de conception d'application (ou des deux).

Une ou deux fois par mois, cette base de données Oracle XE signale des erreurs ORA-4031. Cela ne pointe pas systématiquement vers une partie particulière de la sga. Un exemple récent est:

ORA-04031: unable to allocate 8208 bytes of shared memory ("large pool","unknown object","sort subheap","sort key")

Lorsque cette erreur se produit, si l'utilisateur continue d'actualiser ses données en cliquant sur différents liens, il obtiendra généralement davantage de ce type d'erreurs à des moments différents. Bientôt, il obtiendra les erreurs de page "404 non trouvés".

Le redémarrage de la base de données résout généralement le problème pendant un certain temps, puis environ un mois plus tard, il revient, mais rarement au même endroit du programme (c’est-à-dire qu’il ne semble pas lié à une partie de code particulière) (l’exemple ci-dessus). une erreur a été générée à partir d'une page Apex qui triait plus de 5 000 lignes d'une table).

J'ai essayé d'augmenter sga_max_size de 140M à 256M et j'espère que cela aidera les choses. Bien sûr, je ne saurai pas si cela a aidé depuis que j'ai dû redémarrer la base de données pour changer les paramètres :)

J'utilise Oracle XE 10.2.0.1.0 sur une machine Oracle Enterprise Linux 5 avec 512 Mo de RAM. Le serveur exécute uniquement la base de données, Oracle Apex (v3.1.2) et le serveur Web Apache. Je l'ai installé avec à peu près tous les paramètres par défaut et il fonctionne assez bien depuis environ un an. La plupart des problèmes que j'ai pu résoudre moi-même en ajustant le code de l'application; il n'est pas utilisé de manière intensive et n'est pas un système critique pour l'entreprise.

Je pense que certains paramètres actuels peuvent être pertinents:

pga_aggregate_target        41,943,040
sga_max_size              268,435,456
sga_target                146,800,640
shared_pool_reserved_size   5,452,595
shared_pool_size          104,857,600

Si cela vous aide, voici les tailles SGA actuelles:

Total System Global Area  268435456 bytes
Fixed Size                  1258392 bytes
Variable Size             251661416 bytes
Database Buffers           12582912 bytes
Redo Buffers                2932736 bytes
21
Jeffrey Kemp

Même si vous utilisez ASMM, vous pouvez définir une taille minimale pour le grand pool (MMAN ne le réduira pas en dessous de cette valeur) . Vous pouvez également essayer d'épingler certains objets et d'augmenter SGA_TARGET.

6
Kathryn

N'oubliez pas de fragmentation. Si vous avez beaucoup de trafic, vos pools peuvent être fragmentés et même si vous avez plusieurs Mo disponibles, il ne peut y avoir de bloc supérieur à 4 Ko . Vérifiez la taille du plus grand bloc libre avec une requête du type:

 select
  '0 (<140)' BUCKET, KSMCHCLS, KSMCHIDX,
  10*trunc(KSMCHSIZ/10) "From",
  count(*) "Count" ,
  max(KSMCHSIZ) "Biggest",
  trunc(avg(KSMCHSIZ)) "AvgSize",
  trunc(sum(KSMCHSIZ)) "Total"
from
  x$ksmsp
where
  KSMCHSIZ<140
and
  KSMCHCLS='free'
group by
  KSMCHCLS, KSMCHIDX, 10*trunc(KSMCHSIZ/10)
UNION ALL
select
  '1 (140-267)' BUCKET,
  KSMCHCLS,
  KSMCHIDX,
  20*trunc(KSMCHSIZ/20) ,
  count(*) ,
  max(KSMCHSIZ) ,
  trunc(avg(KSMCHSIZ)) "AvgSize",
  trunc(sum(KSMCHSIZ)) "Total"
from
  x$ksmsp
where
  KSMCHSIZ between 140 and 267
and
  KSMCHCLS='free'
group by
  KSMCHCLS, KSMCHIDX, 20*trunc(KSMCHSIZ/20)
UNION ALL
select
  '2 (268-523)' BUCKET,
  KSMCHCLS,
  KSMCHIDX,
  50*trunc(KSMCHSIZ/50) ,
  count(*) ,
  max(KSMCHSIZ) ,
  trunc(avg(KSMCHSIZ)) "AvgSize",
  trunc(sum(KSMCHSIZ)) "Total"
from
  x$ksmsp
where
  KSMCHSIZ between 268 and 523
and
  KSMCHCLS='free'
group by
  KSMCHCLS, KSMCHIDX, 50*trunc(KSMCHSIZ/50)
UNION ALL
select
  '3-5 (524-4107)' BUCKET,
  KSMCHCLS,
  KSMCHIDX,
  500*trunc(KSMCHSIZ/500) ,
  count(*) ,
  max(KSMCHSIZ) ,
  trunc(avg(KSMCHSIZ)) "AvgSize",
  trunc(sum(KSMCHSIZ)) "Total"
from
  x$ksmsp
where
  KSMCHSIZ between 524 and 4107
and
  KSMCHCLS='free'
group by
  KSMCHCLS, KSMCHIDX, 500*trunc(KSMCHSIZ/500)
UNION ALL
select
  '6+ (4108+)' BUCKET,
  KSMCHCLS,
  KSMCHIDX,
  1000*trunc(KSMCHSIZ/1000) ,
  count(*) ,
  max(KSMCHSIZ) ,
  trunc(avg(KSMCHSIZ)) "AvgSize",
  trunc(sum(KSMCHSIZ)) "Total"
from
  x$ksmsp
where
  KSMCHSIZ >= 4108
and
  KSMCHCLS='free'
group by
  KSMCHCLS, KSMCHIDX, 1000*trunc(KSMCHSIZ/1000);

Code de

5
slovon

Toutes les réponses actuelles traitent du symptôme (épuisement du pool de mémoire partagée) et non du problème, qui consiste à ne pas utiliser de variables de liaison dans vos requêtes sql\JDBC, même si cela ne semble pas nécessaire. Passer des requêtes sans variables de liaison oblige Oracle à "analyser en profondeur" la requête à chaque fois, en déterminant son plan d'exécution, etc. 

https://asktom.Oracle.com/pls/asktom/f?p=100:11:::::p11_question_id:528893984337

Quelques extraits du lien ci-dessus:

"Java prend en charge les variables de liaison, vos développeurs doivent commencer par utiliser des instructions préparées et y lier des entrées. Si vous souhaitez que votre système évolue au-delà de 3 ou 4 utilisateurs, vous le ferez maintenant Ce n’est pas quelque chose à penser, c’est une chose que vous DEVEZ faire. Un effet secondaire: vos problèmes de piscine partagés disparaîtront à peu près. C’est la cause fondamentale. "

"La manière dont fonctionne le pool partagé Oracle (une structure de données en mémoire partagée très importante) Est basée sur le fait que les développeurs utilisent des variables de liaison."

"Les variables de liaison sont SO MASSIVEMENT importantes - je ne peux en aucune façon donner forme ou surestimer leur importance."

2
mancini0

Les éléments suivants ne sont pas nécessaires car ils ne résolvent pas l'erreur:

  1. 1 ps -ef | grep Oracle
  2. Trouvez le smon et tuez le pid pour cela
  3. SQL> Monter le démarrage SQL> 
  4. Créer un pfile à partir de spfile;

Le redémarrage de la base de données va vider votre piscine et cela résout un effet et non le problème.

Fixez votre large_pool afin qu'il ne puisse pas descendre plus bas qu'un certain point ou ajouter de la mémoire et définir une mémoire maximale plus élevée.

0
Tonny de Groot