Bonjour,

un projet m'a sollicité sur un problème de lenteur d'une base 10g. En désactivant le daemon (côté base de données) qui scrute les demandes envoyées par l'OAS, ils ont remarqué que les problèmes de lenteur disparaissaient sur la base.

Le daemon effectue une boucle infinie (while(1)) à l'intérieur de laquelle il appelle la procédure stockée: STD_PIPE_SERVER.RECOIT_MESSAGE qui lui permet de scruter le pipe.
Ce daemon marchait très bien lorsque la base était en 8i. Depuis la migration de la 8i à la 10g les perfs se sont dégradées.

Voici le code source du daemon:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
 
/****************************************************************************\
*
* MODULE : LANCE_DAEMON.PC
*
* TYPE : PC
*
* LIBELLE :
*
* DESCRIPTION : Ce module a pour but de formater une commande a partir 
*               d'une chaine extraite du pipe et de la soumettre a la
*               queue batch SICOM_QUEUE_J ou SICOM_QUEUE_N  .  
*
*
* CREE/MODIFIE (DATE, QUI, NATURE) :
*  31/08/1995    M.CHAKIR    CREATION
*  08/03/1999    T.FOLTIER   MODIFICATION : Utilisation des 2 queues batch
\****************************************************************************/
 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
#define INVARCHAR(a,b) {strcpy((char *) a.arr,b) ; a.len=strlen((char *) a.arr); }
#define SQLCODE         ((int)(sqlca.sqlcode)) 
 
EXEC SQL include sqlca;
 
EXEC SQL begin declare section;
  varchar oUid[100];
  varchar oCommande[2000];
  varchar oType_rep[5];
  varchar oPipe_id[30];
  varchar oReponse[80];
EXEC SQL end declare section;
 
char   zArgument[20][255] ;
char   zParam[20][255] ;
char   zUtilisateur[255] ;
int    status;
int    iNbArg;
 
/**********************************************************************/
void Sqlerror()
{
 EXEC SQL WHENEVER SQLERROR CONTINUE;
 printf("\n\n Erreur!!! %.70s\n\n",sqlca.sqlerrm.sqlerrmc);
 EXEC SQL ROLLBACK RELEASE ;
 exit(1);
}
 
/**********************************************************************/
void connexion()
{
 EXEC SQL WHENEVER SQLERROR DO Sqlerror();
 EXEC SQL CONNECT :oUid;
 printf("\n Connexion etablie \n");
}
 
 
/**********************************************************************/
void Decompose_Comm(char *Commande)
{
  int i,j,k ;
  j=0 ;
  k=0 ;
  for(i=0 ; i <= strlen(Commande) ; i++)
  {
    if( (Commande[i] == ' ') || 
        (Commande[i] == '\n') ||
        (Commande[i] == '\0') )    
    {
            zArgument[j][k] = '\0' ; 
      k=0 ;
      j++ ;
    }
    else
    {
      zArgument[j][k] = Commande[i] ;
      k++ ;
    }
  }
  zArgument[j][k] = '\0' ; 
  iNbArg=j;
  strcpy(zUtilisateur,zArgument[1]);
  strcpy(zArgument[1],"");
  j=0; 
  for(i=0 ;i < iNbArg ;i++)
  {
    if(strcmp(zArgument[i],"") != 0)
    {
      strcpy(zParam[j],zArgument[i]);
      j++;
    }
  }  
}
 
/**********************************************************************/
void Trait_Comm(char *zQueue)
{
  char zCommande[500]; 
    sprintf(zCommande,
      "ksh $COM/siges_submit_process.sh  '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s'  '%s' ",
    	zParam[0],zParam[1],
    	zParam[2],zParam[3],zParam[4],zParam[5],
    	zParam[6],zParam[7],zParam[8]);
 
  printf(" le serveur traite la commande : \n%s\n",zCommande);
  status = system(zCommande);
  printf(" status : [%d] \n",status);
 
}
 
/**********************************************************************/
/* Programme qui va permettre de lancer sur le serveur un demon qui   */
/* sera en attente de demande de service.                             */
/**********************************************************************/
int main(int argc,char *argv[])
{
  char zConnectString [500]; 
 
    sprintf(zConnectString, getenv("CONNECT_STRING")); 
    printf("\n Demande de Connexion sur %s " , zConnectString  ); 
 
    strcpy((char *) oUid.arr,zConnectString);
    oUid.len = strlen((char *) oUid.arr);
    connexion();
    EXEC SQL WHENEVER SQLERROR DO Sqlerror();
    while(1)
    {
      EXEC SQL EXECUTE
        BEGIN
          :oCommande :=  STD_PIPE_SERVER.RECOIT_MESSAGE;
          :oCommande := replace(:oCommande,'\','\\' ); 
        END;
      END-EXEC;
 
      oCommande.arr[oCommande.len]='\0';
      printf(" Commande recue : \n(%s)\n",(char *) oCommande.arr);
      if(strcmp((char *) oCommande.arr,"LOCAL   STOP") == 0)
      {
        break ;
      }
      Decompose_Comm((char *) oCommande.arr);
      INVARCHAR(oPipe_id,zArgument[2]);  
      EXEC SQL EXECUTE
        BEGIN
          STD_PIPE_SERVER.ENVOIT_REP('DEB','Traitement soumis, consulter les messages dans suivi de traitements',:oPipe_id);
        END;
      END-EXEC;
 
        Trait_Comm("")  ;
 
    }
    printf("\n Deconnexion du daemon...");
    EXEC SQL ROLLBACK RELEASE ;
    exit(0);
}

voici le code de la procédure stockée qui permet de scruter le PIPE:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
 
create or replace PACKAGE BODY STD_PIPE_SERVER
IS
ID_PIPE			VARCHAR2(40);
--***********************************************************************
--
--***********************************************************************
PROCEDURE ENVOIT_REP(TYPE_REP VARCHAR2, REP VARCHAR2, PIPE_REP VARCHAR2 )
IS
S NUMBER;
BEGIN
  DBMS_PIPE.PURGE(PIPE_REP);
  DBMS_PIPE.PACK_MESSAGE(TYPE_REP);
  DBMS_PIPE.PACK_MESSAGE(REP);
  S := DBMS_PIPE.SEND_MESSAGE(PIPE_REP);
END;
 
--***********************************************************************
--
--***********************************************************************
PROCEDURE DAEMON_STOP(PIPE_REP VARCHAR2 )
IS
S NUMBER;
BEGIN
  DBMS_PIPE.PURGE(PIPE_REP);
  DBMS_PIPE.PACK_MESSAGE('1');
  DBMS_PIPE.PACK_MESSAGE(''); 
  DBMS_PIPE.PACK_MESSAGE('');
  DBMS_PIPE.PACK_MESSAGE('LOCAL');
  DBMS_PIPE.PACK_MESSAGE('');
  DBMS_PIPE.PACK_MESSAGE('STOP');
  S := DBMS_PIPE.SEND_MESSAGE(PIPE_REP);
END;
-- ***********************************************************************
--
-- ***********************************************************************
FUNCTION RECOIT_MESSAGE
RETURN VARCHAR2
IS
S			NUMBER;
VERSION_PROTOCOL	VARCHAR2(40);
NOM_PROG		VARCHAR2(40);
CHAINE_CONNECT		VARCHAR2(100);
SITE			VARCHAR2(40);
PARAMETRES		VARCHAR2(500);
EXEC_COMMANDE		VARCHAR2(2000);
BEGIN
  S := DBMS_PIPE.RECEIVE_MESSAGE('STD$PIPE$EXEC');
  IF (S <> 0)
  THEN
    RAISE_APPLICATION_ERROR(-20000,'Error: '||TO_CHAR(S)||' READING PIPE');
  END IF;
  DBMS_PIPE.UNPACK_MESSAGE(VERSION_PROTOCOL);
  IF (VERSION_PROTOCOL <> '1')
  THEN
     RAISE_APPLICATION_ERROR(-20000,'Bad Protocol: '||VERSION_PROTOCOL);
  ELSE
   DBMS_PIPE.UNPACK_MESSAGE(ID_PIPE);
   DBMS_PIPE.UNPACK_MESSAGE(CHAINE_CONNECT);
   DBMS_PIPE.UNPACK_MESSAGE(NOM_PROG);
   DBMS_PIPE.UNPACK_MESSAGE(SITE);
   IF ((SITE <> 'LOCAL') AND (SITE <> 'DISTANT'))
   THEN
      RAISE_APPLICATION_ERROR(-20000,'Bad Parameter: '||SITE);
   END IF;
   DBMS_PIPE.UNPACK_MESSAGE(PARAMETRES);
   EXEC_COMMANDE := NOM_PROG||' '||CHAINE_CONNECT||' '||ID_PIPE||' '||PARAMETRES;
   RETURN(EXEC_COMMANDE);
  END IF;
END;
END;
Au début je croyais qu'il fallait ajouter un SLEEP dans le shell mais en fait en regardant la doc oracle sur le package DBMS_PIPE, je me suis rendu compte que la procédure DBMS_PIPE.RECEIVE_MESSAGE faisait lui même une sorte de pause.

Voyez vous quelque chose dans le code qui pourrait altérer les performances à ce point ?