IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Sybase Discussion :

[ASE] Erreur 941 - Illegal database context operation


Sujet :

Sybase

  1. #1
    Rédacteur
    Avatar de abelman
    Inscrit en
    Février 2003
    Messages
    1 106
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 1 106
    Points : 2 629
    Points
    2 629
    Par défaut [ASE] Erreur 941 - Illegal database context operation
    Bonjour à tous.

    Je m'essaye à écrire une proc stockée sur Sybase ASE 11.9 (je sais, ce n'est
    plus maintenu !!)
    La voici. C'est une proc qui renvoie des valeurs qui servent pour les clés
    primaires numériques

    Lorsque je l'execute via transact SQL je suis déconnecté et j'ai une
    méchante erreur dans le log de Sybase: 941 - Illegal database context
    operation

    Comment faire pour la résoudre?
    J'ai essayé la solution proposé ici mais rien à faire.
    Merci de votre aide.

    Abel

    Erreur obtenue (extrait log du serveur)
    --------------------------------------------
    00:00000:00010:2006/07/12 15:27:10.87 server Error: 941, Severity: 20, State: 1
    00:00000:00010:2006/07/12 15:27:10.87 server Illegal database context operation.
    00:00000:00010:2006/07/12 15:27:10.87 kernel ************************************
    00:00000:00010:2006/07/12 15:27:10.87 kernel SQL causing error : DECLARE @i decimal
    exec stpr_get_counter 'NAME',@i
    SELECT @i
    00:00000:00010:2006/07/12 15:27:10.87 kernel ************************************
    00:00000:00010:2006/07/12 15:27:10.89 server SQL Text: DECLARE @i decimal
    exec stpr_get_counter 'NAME',@i
    SELECT @i
    00:00000:00010:2006/07/12 15:27:10.89 kernel curdb = 5 pstat = 0x10000 lasterror = 941
    00:00000:00010:2006/07/12 15:27:10.89 kernel preverror = 0 transtate = 0
    00:00000:00010:2006/07/12 15:27:10.89 kernel curcmd = 224 program = SQL_Advantage
    00:00000:00010:2006/07/12 15:27:10.89 kernel pc: 0x8a2977 os_get_cur_stk_desc+ 0x57 (0x13ff04c, 0x1d001d, 0x13ff04c, 0x0)
    00:00000:00010:2006/07/12 15:27:10.89 kernel pc: 0x8a2977 os_get_cur_stk_desc+ 0x57 (0x13ff04c, 0x13ff5a0, 0x270f, 0x2)
    00:00000:00010:2006/07/12 15:27:10.89 kernel pc: 0x883514 pcstkwalk+ 0x224 (0x1d001d, 0x2, 0x270f, 0x0)
    00:00000:00010:2006/07/12 15:27:10.89 kernel pc: 0x8830ae ucstkgentrace+ 0x1ce (0x0, 0x1, 0x14, 0x0)
    00:00000:00010:2006/07/12 15:27:10.89 kernel pc: 0x862864 ucbacktrace+ 0x84 (0x0, 0xffffffff, 0x13ff964, 0x4527a8)
    00:00000:00010:2006/07/12 15:27:10.89 kernel pc: 0x405fe6 terminate_process+ 0x566 (0x13ff9c4, 0x639a02, 0x9, 0x29)
    00:00000:00010:2006/07/12 15:27:10.89 kernel pc: 0x4527ea close_network+ 0x1a (0x9, 0x29, 0x14, 0x1)
    00:00000:00010:2006/07/12 15:27:10.89 kernel pc: 0x4527a8 hdl_default+ 0x48 (0x9, 0x29, 0x14, 0x1)
    00:00000:00010:2006/07/12 15:27:10.89 kernel pc: 0x639a02 s_handle+ 0x162 (0x9, 0x29, 0x14, 0x1)
    00:00000:00010:2006/07/12 15:27:10.89 kernel pc: 0x452413 ex_raise+ 0x193 (0xffffffff, 0x202d2594, 0x20010060, 0x0)
    00:00000:00010:2006/07/12 15:27:10.89 kernel pc: 0x47597c closedb+ 0x2ac (0x208192ac, 0x20819324, 0x0, 0x0)
    00:00000:00010:2006/07/12 15:27:10.89 kernel pc: 0x65a328 execproc+ 0x828 (0x202d2594, 0x81a, 0x2081edec, 0x0)
    00:00000:00010:2006/07/12 15:27:10.89 kernel pc: 0x65467a s_execute+ 0x213a (0x2080c800, 0x202d2594, 0x20010060, 0x0)
    00:00000:00010:2006/07/12 15:27:10.89 kernel [Handler pc: 0x6398a0 s_handle installed by the following function:-]
    00:00000:00010:2006/07/12 15:27:10.89 kernel pc: 0x63678f sequencer+ 0x15f (0x2081ed74, 0x2081edec, 0x0, 0x0)
    00:00000:00010:2006/07/12 15:27:10.89 kernel pc: 0x659d8f execproc+ 0x28f (0x21, 0x202d2594, 0x202d2594, 0x20288e28)
    00:00000:00010:2006/07/12 15:27:10.89 kernel pc: 0x65467a s_execute+ 0x213a (0x2082d800, 0x21, 0x202d97d1, 0x202d2594)
    00:00000:00010:2006/07/12 15:27:10.89 kernel [Handler pc: 0x6398a0 s_handle installed by the following function:-]
    00:00000:00010:2006/07/12 15:27:10.89 kernel pc: 0x63678f sequencer+ 0x15f (0x0, 0x20014b38, 0x1c001c, 0x20013830)
    00:00000:00010:2006/07/12 15:27:10.89 kernel pc: 0x436d31 tdsrecv_language+ 0xc1 (0x3, 0x4000, 0x20014b38, 0x1c001c)
    00:00000:00010:2006/07/12 15:27:10.89 kernel [Handler pc: 0x452660 hdl_backout installed by the following function:-]
    00:00000:00010:2006/07/12 15:27:10.89 kernel [Handler pc: 0x5c0c40 ut_handle installed by the following function:-]
    00:00000:00010:2006/07/12 15:27:10.89 kernel [Handler pc: 0x5c0c40 ut_handle installed by the following function:-]
    00:00000:00010:2006/07/12 15:27:10.89 kernel pc: 0x40dc1c conn_hdlr+ 0xb5c (0x20014b38, 0x20013830, 0x1c001c, 0x20014b38)
    00:00000:00010:2006/07/12 15:27:10.89 kernel pc: 0x89c1c6 kpntwrapper+ 0x96 (0x89c130, 0x20014b38, 0x0, 0x0)
    00:00000:00010:2006/07/12 15:27:10.96 kernel pc: 0x7c80b50b kernel32.dll (0x661b4e, 0x20821800, 0xff, 0x2)
    00:00000:00010:2006/07/12 15:27:10.96 kernel end of stack trace, spid 10, kpid 1900573, suid 11
    ------------------------
    Transact sql pour executer la proc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ----------
    DECLARE @i decimal
    exec stpr_get_counter 'NAME',@i
    SELECT @i
    ----------
    Code de la proc
    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
    ------------------------------------------------
    CREATE Procedure stpr_get_counter
    @countername VARCHAR(128),
    @countervalue DECIMAL = NULL OUTPUT
    AS
     
     DECLARE @errmsg VARCHAR(255)
     DECLARE @strQuery VARCHAR(255)
     DECLARE @ok INT
      DECLARE @nextvalue DECIMAL
     
      SELECT @ok = 0
     SELECT @nextvalue = -1
     
     SET NOCOUNT ON
     
    -- Highest transaction level. Only one connection can enter this at the same 
    time
     SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
     BEGIN TRAN GET_COUNTER
     
     SELECT @ok = COUNT(*) FROM ref_counters WHERE cnt_name = @countername
     IF @@ERROR > 0
     BEGIN
      SELECT @errmsg = 'Failed on query SELECT COUNT(*) FROM ref_counters'
      GOTO ERROR_HANDLER
     END
    -- Insert countername entry if necessary
     IF @ok = 0
     BEGIN
      SELECT @strQuery = 'INSERT INTO ref_counters (cnt_name, cnt_lastvalue) 
    VALUES (''' +  @countername + ''', 0)'
      EXEC @strQuery
      IF @@ERROR > 0
      BEGIN
       SELECT @errmsg = 'Failed on statement INSERT INTO ref_counters'
       GOTO ERROR_HANDLER
      END
     END
     
    -- Getting next counter value
     SELECT @nextvalue = cnt_lastvalue + 1 FROM ref_counters WHERE cnt_name = 
    @countername
     IF @@ERROR > 0
     BEGIN
      SELECT @errmsg = 'Failed on query SELECT cnt_lastvalue+1 FROM 
    ref_counters'
      GOTO ERROR_HANDLER
     END
    -- Update last value in counters table
     UPDATE ref_counters SET cnt_lastvalue = @nextvalue WHERE cnt_name = 
    @countername
     IF @@ERROR > 0
     BEGIN
      SELECT @errmsg = 'Failed on statement UPDATE ref_counters'
      GOTO ERROR_HANDLER
     END
    -- Return counter
     SELECT @countervalue = @nextvalue
     
     SELECT @countervalue
     
    -- Commit transaction
     COMMIT TRAN GET_COUNTER
     
     SET NOCOUNT OFF
     RETURN 0
     
    ERROR_HANDLER:
     ROLLBACK TRAN GET_COUNTER
     SET NOCOUNT OFF
     RAISERROR @@ERROR
     PRINT @errmsg
     RETURN @@ERROR
     
    ------------------------------------------

  2. #2
    Membre chevronné

    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 307
    Détails du profil
    Informations personnelles :
    Âge : 64
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 307
    Points : 1 828
    Points
    1 828
    Par défaut
    Bonjour,

    Je viens de répondre sur les forums Sybase, mais je peux reposter ici...

    Le problème vient à priori du "execute immediate" qui n'est disponible qu'à partir de la version 12. De plus la syntaxe correcte serait:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    EXEC (@sqlCommand)
    où les parenthèses sont obligatoire pour indiquer que @sqlCommand ne contient pas le nom d'une proc stockée ou d'une RPC.

    Michael
    Michael Peppler
    Membre de TeamSybase - www.teamsybase.com

    "A successful [software] tool is one that was used to do something undreamed of by its author." -- S. C. Johnson

  3. #3
    Rédacteur
    Avatar de abelman
    Inscrit en
    Février 2003
    Messages
    1 106
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 1 106
    Points : 2 629
    Points
    2 629
    Par défaut


    Si ça ne vous dérange pas on peut continuer ici?

    Citation Envoyé par sur le forum sybase j'ai répondu
    Merci de votre aide.

    J'ai traduit le code d'une proc stock SQL SERVER 2000 et avant il y avait
    les parenthèses.
    J'ai enlever les parenthèses car la proc ne fonctionnait pas avec (erreur
    script création)

    Savez vous quelles sont les alternatives à EXEC pour la 11.9 ?

    Merci

    Abel
    Edit : PS: Auriez vous quelques instants à consacrer à ceci ?

  4. #4
    Rédacteur
    Avatar de abelman
    Inscrit en
    Février 2003
    Messages
    1 106
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 1 106
    Points : 2 629
    Points
    2 629
    Par défaut
    J'ai trouvé ça et apparement ça marche
    http://www.sypron.nl/dynsqlcis.html

    Merci

  5. #5
    Membre chevronné

    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 307
    Détails du profil
    Informations personnelles :
    Âge : 64
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 307
    Points : 1 828
    Points
    1 828
    Par défaut
    C'était exactement ce que j'allais suggérer...

    Michael
    Michael Peppler
    Membre de TeamSybase - www.teamsybase.com

    "A successful [software] tool is one that was used to do something undreamed of by its author." -- S. C. Johnson

  6. #6
    Rédacteur/Modérateur

    Avatar de Fabien Celaia
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Octobre 2002
    Messages
    4 222
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Service public

    Informations forums :
    Inscription : Octobre 2002
    Messages : 4 222
    Points : 19 554
    Points
    19 554
    Billets dans le blog
    25
    Par défaut
    Citation Envoyé par abelman
    J'ai trouvé ça et apparement ça marche
    http://www.sypron.nl/dynsqlcis.html

    Merci
    Oui, c'est un grand classique que de boucler sur son propre serveur via CIS... par contre attention aux perfs...
    Sr DBA Oracle / MS-SQL / MySQL / Postgresql / SAP-Sybase / Informix / DB2

    N'oublie pas de consulter mes articles, mon blog, les cours et les FAQ SGBD

    Attention : pas de réponse technique par MP : pensez aux autres, passez par les forums !

  7. #7
    Rédacteur
    Avatar de abelman
    Inscrit en
    Février 2003
    Messages
    1 106
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 1 106
    Points : 2 629
    Points
    2 629
    Par défaut
    Re, j'ai mis résolu trop vite.

    J'ai suivi à la lettre les indications du site sypron

    J'ai configuré mon serveur pour CIS avec les deux scripts et cela a fonctionné.

    Par contre quand j'éxecute ma proc, il me dit qu'il ne trouve pas la table ref_counters. (REquête INSERT INTO ref_counters .. dans ma proc plus haut)

    Qui existe bel et bien.

    J'ai fait quelques test et j'ai vu que ça marche quand je prefixe la table par le nom de la base de données.

    J'arrive à le faire pour le insert.

    Comme ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    	SELECT @db=db_name() 
        	PRINT @db 
            SELECT @strQuery = 'INSERT INTO ' + @db + '..ref_counters (cnt_name, cnt_lastvalue) VALUES (''' +  @countername + ''', 0)'  
            PRINT @strQuery 
            EXEC sp_exec_dynsql @strQuery
    Mais comment faire pour ce genre de requête pour prefixer???

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    --  Getting next counter value  
        SELECT @nextvalue = cnt_lastvalue + 1 FROM ref_counters WHERE cnt_name = @countername  
        IF @@ERROR > 0  
        BEGIN  
            SELECT @errmsg = 'Failed on query SELECT cnt_lastvalue+1 FROM ref_counters'  
            GOTO ERROR_HANDLER  
        END  
    --  Update last value in counters table  
        UPDATE ref_counters SET cnt_lastvalue = @nextvalue WHERE cnt_name = @countername
    Il faut utiliser les curseurs? Je ne sais pas les utiliser (pr l'instant). Vous connaissez des tutos dessus? ou bien avez vous d'autres suggestions?

    Merci

  8. #8
    Rédacteur
    Avatar de abelman
    Inscrit en
    Février 2003
    Messages
    1 106
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 1 106
    Points : 2 629
    Points
    2 629
    Par défaut


    Merci de ne pas tenir compte de mon dernier message.
    Je vais prefixer le nom de la base en dur directement dans les requêtes car la proc est un objet d'une seule base ...

    @+

  9. #9
    Rédacteur
    Avatar de abelman
    Inscrit en
    Février 2003
    Messages
    1 106
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 1 106
    Points : 2 629
    Points
    2 629
    Par défaut
    Re bonjour,

    Alors j'ai essayer d'utiliser ma nouvelle proc stock avec la gestion du Exec contourné avec les Remote IO. (Sybase 11.9.2)

    ça ne marche pas.

    Le code suivant bloque et je n'ai plus la main. (Je dois tuer l'application pour reprendre la main)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    declare @cpt decimal
    exec @cpt=stpr_get_counter 'compteurx'
    select @cpt
    Quand je regarde l'état du processus dans Sybase central, j'ai:
    ID=1
    Programme = SQL_Advantage
    Commande= EXECUTE
    Login=sa
    Etat = remote i/o

    Je n'ai rien dans les logs.

    Une idée? Devrais je avoir un service annexe Sybase qui tourne? Qu'est ce que c'est qu'un XP server par exemple? Dans mes logs j'ai toujours un 'XP Server is not running' lors de l'arrêt du serveur.

    JE remet le code de la proc stock ici
    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
    ------------------------------------------------
     CREATE Procedure stpr_get_counter  
    @countername VARCHAR(128),  
    @countervalue DECIMAL = NULL OUTPUT  
    AS  
     
        DECLARE @errmsg VARCHAR(255)  
        DECLARE @strQuery VARCHAR(255)  
        DECLARE @ok INT  
        DECLARE @nextvalue DECIMAL  
        DECLARE @dbname VARCHAR(50) 
     
        SELECT @ok = 0  
        SELECT @nextvalue = -1  
     
        SET NOCOUNT ON  
     
    --  Highest transaction level. Only one connection can enter this at the same time  
        SET TRANSACTION ISOLATION LEVEL SERIALIZABLE  
        BEGIN TRAN GET_COUNTER  
     
    --  Search for coutername entry in counter table  
        --SET @ok = 0  
        SELECT @ok = COUNT(*) FROM ref_counters WHERE cnt_name = @countername  
        IF @@ERROR > 0  
        BEGIN  
            SELECT @errmsg = 'Failed on query SELECT COUNT(*) FROM ref_counters'  
            GOTO ERROR_HANDLER  
        END  
    -- Insert countername entry if necessary  
        IF @ok = 0  
        BEGIN  
        		SELECT @dbname=db_name() 
        		PRINT @dbname 
            SELECT @strQuery = 'INSERT INTO ' + @dbname + '..ref_counters (cnt_name, cnt_lastvalue) VALUES (''' +  @countername + ''', 0)'  
            PRINT @strQuery 
            EXEC sp_exec_dynsql @strQuery  
            IF @@ERROR > 0  
            BEGIN  
                SELECT @errmsg = 'Failed on statement INSERT INTO ref_counters'  
                GOTO ERROR_HANDLER  
            END  
        END  
     
    --  Getting next counter value  
        SELECT @nextvalue = cnt_lastvalue + 1 FROM ref_counters WHERE cnt_name = @countername  
        IF @@ERROR > 0  
        BEGIN  
            SELECT @errmsg = 'Failed on query SELECT cnt_lastvalue+1 FROM ref_counters'  
            GOTO ERROR_HANDLER  
        END  
    --  Update last value in counters table  
        UPDATE ref_counters SET cnt_lastvalue = @nextvalue WHERE cnt_name = @countername  
        IF @@ERROR > 0  
        BEGIN  
            SELECT @errmsg = 'Failed on statement UPDATE ref_counters'  
            GOTO ERROR_HANDLER  
        END  
    --  Return counter  
        SELECT @countervalue = @nextvalue  
     
        SELECT @countervalue  
     
    --  Commit transaction  
        COMMIT TRAN GET_COUNTER  
     
        SET NOCOUNT OFF  
        RETURN @countervalue
     
    ERROR_HANDLER:  
        ROLLBACK TRAN GET_COUNTER  
        SET NOCOUNT OFF  
        PRINT @errmsg 
        --RAISERROR @@ERROR   
        RETURN @@ERROR

  10. #10
    Membre chevronné

    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 307
    Détails du profil
    Informations personnelles :
    Âge : 64
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 307
    Points : 1 828
    Points
    1 828
    Par défaut
    Le XP server permet d'exécuter une command OS ou du code C ad-hoc comme une proc stockée. Ce module n'est donc pas en cause ici.

    Je suspecte qu'il y a peut-être un problème de logique au niveau des transactions avec l'appel imbriqué de l'insert via sp_remote_sql. Il faut savoir que cet appel ne peut pas être fait dans le contexte de la transaction en cours, et si la requete qui est exécutée par sp_remote_sql doit accèder à une table qui est bloquée par la transaction démarrée dans la proc stpr_get_counter alors elle risque de tout bloquer.

    Pour vérifier il suffit d'ouvirir une connexion supplémentaire et de faire un sp_who. Si le process est bloqué en "lock sleep" alors cela confirmerait cette analyse.

    Michael
    Michael Peppler
    Membre de TeamSybase - www.teamsybase.com

    "A successful [software] tool is one that was used to do something undreamed of by its author." -- S. C. Johnson

  11. #11
    Rédacteur
    Avatar de abelman
    Inscrit en
    Février 2003
    Messages
    1 106
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 1 106
    Points : 2 629
    Points
    2 629
    Par défaut
    Effectivement c'est le cas.

    Quand j'enlève le niveau d'isolation maximum
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
    ça fonctionne très bien.

    Le problème c'est que cette procedure sera très probablement sollicitée par plusieurs processus différents et de manière simultanée souhaitant obtenir la même valeur de compteur.

    Comment faire dans ce cas pour garantir l'intégrité du compteur retourné? (pas de doublons)

    Merci de votre aide en tout cas.

  12. #12
    Membre chevronné

    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 307
    Détails du profil
    Informations personnelles :
    Âge : 64
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 307
    Points : 1 828
    Points
    1 828
    Par défaut
    On pourrait imaginer créer une table annexe pour controler l'accès. Cette table n'aurait qu'un enregistrement qui serait mis à jour (sans commit) en entrant dans la proc. Cela devrait permettre de serialiser l'accès.

    Par example:

    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
     
    create table the_semaphore(spid int)
    go
    insert the_semaphore values(0)
    go
     
    create proc get_counter ...
    begin
     
    begin tran
     
    update the_semaphore set spid = @@spid
     
    ... le reste de la proc ...
     
    commit tran
    En principe cela devrait permettre l'exécution unitaire de la proc get_counter.

    Michael
    Michael Peppler
    Membre de TeamSybase - www.teamsybase.com

    "A successful [software] tool is one that was used to do something undreamed of by its author." -- S. C. Johnson

  13. #13
    Rédacteur
    Avatar de abelman
    Inscrit en
    Février 2003
    Messages
    1 106
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 1 106
    Points : 2 629
    Points
    2 629
    Par défaut
    mmh ..
    Je suis désolé mais là je crois que mes limites sur le Transact SQL sont atteintes.

    La simple présence d'un update suffira à sérialiser l'accès? Car j'ai déjà un update dans le code de la proc.

    Ou bien il faut en plus que je vérifie à la fin de la proc que le spid présent dans la table semaphore est bien celui de la connection en cours, et si ce n'est pas le cas recommencer le traitement (ce qui implique une boucle et ne me plait pas trop car ça peut partir théoriquement à l'infini)

    Un truc comme ça ?

    Par ailleurs au lieu de creer une table je rajouterai plutot une colonne spid à la table ref_counters

    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
    create proc get_counter ...
    begin
     
    begin tran
     
    start:
    update the_semaphore set spid = @@spid
     
    ... le reste de la proc ...
     
    declare @sem int
    select @sem = spid from the_semaphore
    if @sem <> @@spid then
    goto start -- gerer un nombre max d'itérations avant de renvoyer erreur
     
    commit tran

  14. #14
    Membre chevronné

    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 307
    Détails du profil
    Informations personnelles :
    Âge : 64
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 307
    Points : 1 828
    Points
    1 828
    Par défaut
    L'idée est de créer un verrou au début de l'accès à la proc. Avec une table avec un seul row le verrou posé par un UPDATE sera un EX_TABLE (exclusif sur la table). Comme l'accès suivant veut faire le même verrou il devra attendre que le précedant execute le COMMIT (ce qui libère le verrou).

    L'idée est évidemment d'éviter un verrou sur la table ref_counters, puisque cette table doit être accèdée par l'appel à sp_remote_sql, ce qui se fait via une autre connexion, et donc dans un contexte transactionel différent. Si notre proc pose un verrou sur ref_counters alors l'appel à sp_remote_sql pour faire une mise à jour de ref_counters va bloquer (comme on a vu avec l'utilisation du SET TRANSACTION LEVEL...)

    Donc on crée un verrou dans une autre table (la donnée qu'on met dans cette autre table importe peu) pour arriver au comportement souhaité.

    C'est évidemment assez tordu, mais comme on essaie de faire de l'EXECUTE IMMEDIATE quand cette fonctionalité n'existe pas vraiment il faut trouver des moyens détournés...

    Michael
    Michael Peppler
    Membre de TeamSybase - www.teamsybase.com

    "A successful [software] tool is one that was used to do something undreamed of by its author." -- S. C. Johnson

  15. #15
    Rédacteur
    Avatar de abelman
    Inscrit en
    Février 2003
    Messages
    1 106
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 1 106
    Points : 2 629
    Points
    2 629
    Par défaut
    Merci beaucoup c'est clair et cohérent..
    Et cela semble fonctionner ... pour l'instant ;-)

    Encore merci

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Sunopsis V4 Sybase ASE : erreur JZ0P1
    Par n.roussaly dans le forum ODI (ex-Sunopsis)
    Réponses: 1
    Dernier message: 20/06/2007, 16h10
  2. Sybase ASE : erreur JZ0P1
    Par n.roussaly dans le forum Sybase
    Réponses: 11
    Dernier message: 20/06/2007, 16h06
  3. Message d'erreur "Repérage illegal"
    Par tiboo dans le forum Administration système
    Réponses: 3
    Dernier message: 18/04/2007, 20h33
  4. Réponses: 7
    Dernier message: 17/10/2006, 13h55
  5. Réponses: 4
    Dernier message: 17/01/2006, 18h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo