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

  1. #1
    Modérateur
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    août 2006
    Messages
    15 856
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : août 2006
    Messages : 15 856
    Points : 31 374
    Points
    31 374
    Billets dans le blog
    4

    Par défaut Enchaînement de procédures avec des commits et rollbacks.

    Bonjour,

    Soit un enchaînement de procédures pour créer un candidat qui est une personne-physique :

    Algorithmiquement dans la procédure de création du candidat :
    1) Si l'identifiant de la personne physique est null ou n'existe pas, j'appelle la procédure de création d'une personne physique.
    2) La procédure de création d'une personne physique contient une transaction qui rollback en cas d'erreur sur une clé étrangère fournie ou qui commit si tout va bien. Elle renvoie alors l'identifiant de la personne créée.
    3) On vérifie d'autres données nécessaires à la création du candidat puis on enregistre le candidat. Il peut là aussi y avoir des erreurs de clés étrangères qui sont capturées en tant qu'exception et la procédure rollback ou commit si tout va bien.

    Si je démarre la transaction dans la procédure de création du candidat, un éventuel rollback va t-il annuler la création de la personne physique ?
    Autrement dit, est-ce que je peux encapsuler les transactions par le jeu de l'enchaînement des procédures ?
    Sinon, dois-je gérer la transaction globale en dehors des procédures ?

    Dans l'application, je peux être amené à :
    - créer un utilisateur qui entraîne la création d'une personne physique ;
    - créer un candidat qui entraîne la création d'une personne physique ;
    - créer un étudiant qui entraîne la création d'un candidat qui entraîne la création d'une personne physique ;
    - créer un autre type de personne qui entraîne la création d'une personne physique...

    La procédure de création d'une personne physique ajoute d'abord une personne (qui peut aussi être une personne morale) puis une personne physique.
    J'y ai mis une transaction pour rollback la création de la personne en cas d'erreur lors de la création de la personne physique.

    En principe, je ne créerai jamais de personne physique sans passer par la création du type de cette personne (utilisateur, candidat, étudiant...) mais je n'aime pas l'idée qu'on puisse le faire vu l'existence de la procédure.

    Bref, j'aimerais avoir vos avis sur la meilleur façon de gérer ça en empêchant de créer des personnes inutiles dans la BDD.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  2. #2
    Rédacteur
    Avatar de SQLpro
    Homme Profil pro
    Expert SGBDR & SQL, spécialiste Microsoft SQL Server
    Inscrit en
    mai 2002
    Messages
    18 145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert SGBDR & SQL, spécialiste Microsoft SQL Server
    Secteur : Conseil

    Informations forums :
    Inscription : mai 2002
    Messages : 18 145
    Points : 42 447
    Points
    42 447

    Par défaut

    Il faut que tu regarde par un simple test si le modèle de gestion des transactions est symétrique ou asymétrique.
    Symétrique => autant de finalisation (COMMIT ou ROLLBACK) que de BGIN
    Asymétrique => le premier ROLLBACK met fin à l'état transactionnel

    Pour info c'est le modèle asymétrique qui a été utilisé par Microsoft SQL Server, c'est le plus sage et le plus performant. Mais il faut connaître l'état transactionnel par un moyen ou un autre. Dans MS SQL Server tu peut le savoir avec la fonction XACT_STATE() qui renvoie 0 si la transaction a été finalisée.

    Cherche dans la doc MySQL l'équivalent.

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence * * * * *

  3. #3
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    février 2011
    Messages
    3 545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : février 2011
    Messages : 3 545
    Points : 11 071
    Points
    11 071

    Par défaut

    Salut à tous.

    Citation Envoyé par CinePhil
    Si je démarre la transaction dans la procédure de création du candidat, un éventuel rollback va t-il annuler la création de la personne physique ?
    Je ne sais pas trop comment vous gérez vos transaction, mais normalement un "commit" valide tout depuis le dernier "start transaction".
    Même remarque pour le "rollback" où celui-ci détricote tout depuis le dernier "start transaction".
    En fait, la structure est la suivante :
    --> au début, on fait un "start transaction".
    --> à la fin, on fait soit un "commit" soit un "rollback".

    Ceci correspond à :
    Citation Envoyé par SQLPRO
    Asymétrique => le premier ROLLBACK met fin à l'état transactionnel
    Une remarque importante : il n'est pas possible de démarrer une transaction à l'intérieur d'une autre transaction !

    La structure de vos transactions est la suivante :
    (1) --> start transaction
    (1) --> commit ou rollback
    (2) --> start transaction
    (2) --> commit ou rollback
    (3) --> start transaction
    (3) --> commit ou rollback

    Par contre, il est interdit de faire cela :

    (1) --> start transaction
    (2) --> start transaction
    (2) --> commit ou rollback
    (1) --> commit ou rollback

    Sauf que cette explication est dans le mode de fonctionne de base.
    Il existe ce que l'on nomme un point de sauvegarde ("savepoint"), qui permet de gérer cela !
    On peut annuler tout ce qui a été fait entre ce point et le "rollback to savepoint nom_du_savepoint".
    Je ne sais pas trop si cela correspond à votre attente, à savoir l'encapsulation de vos grappes de données.
    Pour supprimer un point de sauvegarde, il suffit de faire un "release nom_du_savepoint".

    Citation Envoyé par CinePhil
    Autrement dit, est-ce que je peux encapsuler les transactions par le jeu de l'enchaînement des procédures ?
    Comme je l'ai dit précédemment, ce n'est pas possible, sauf si vous utilisez un "savepoint"."

    Citation Envoyé par CinePhil
    Sinon, dois-je gérer la transaction globale en dehors des procédures ?
    Il n'est pas nécessaire de le faire à l'extérieur d'une procédure.
    En fait, comment gérez-vous votre grappe de données ?

    Citation Envoyé par CinePhil
    Dans l'application, je peux être amené à :
    - créer un utilisateur qui entraîne la création d'une personne physique ;
    - créer un candidat qui entraîne la création d'une personne physique ;
    - créer un étudiant qui entraîne la création d'un candidat qui entraîne la création d'une personne physique ;
    - créer un autre type de personne qui entraîne la création d'une personne physique...
    Ça, c'est une grappe de données.

    Si vous rencontrez un problème sur la dernière création, vous êtes obligé de tout annuler.

    Citation Envoyé par CinePhil
    Bref, j'aimerais avoir vos avis sur la meilleur façon de gérer ça en empêchant de créer des personnes inutiles dans la BDD.
    La règle de base est de gérer votre grappe de données dans sa globalité. A savoir, on valide tout ou bien on rejette tout !

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  4. #4
    Modérateur
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    août 2006
    Messages
    15 856
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : août 2006
    Messages : 15 856
    Points : 31 374
    Points
    31 374
    Billets dans le blog
    4

    Par défaut

    Merci Artemus !
    Une remarque importante : il n'est pas possible de démarrer une transaction à l'intérieur d'une autre transaction !
    Je m'en doutais un peu mais je n'étais pas sûr, du fait que les transactions sont dans des procédures différentes.

    Il existe ce que l'on nomme un point de sauvegarde ("savepoint"), qui permet de gérer cela !
    On peut annuler tout ce qui a été fait entre ce point et le "rollback to savepoint nom_du_savepoint".
    Je ne sais pas trop si cela correspond à votre attente, à savoir l'encapsulation de vos grappes de données.
    Pour supprimer un point de sauvegarde, il suffit de faire un "release nom_du_savepoint".
    Il est bien possible que ce soit ce qu'il me faut, en effet.

    Ça, c'est une grappe de données.

    Si vous rencontrez un problème sur la dernière création, vous êtes obligé de tout annuler.
    C'est bien ça que je veux, en effet.

    En simplifiant, voici mon déroulement actuel :
    Procédure A
    ************ Emplacement potentiel d'un START TRANSACTION ***************
    => selon une condition, appelle une procédure B
    -- Procédure B
    -- Start transaction
    -- Ajoute une ligne dans une table
    -- Utilise l'ID du premier ajout pour ajouter dans une seconde table
    -- Si erreur de clé étrangère lors de l'ajout dans la seconde table -> Rollback et SIGNAL pour arrêter le déroulement
    -- Sinon -> Commit et retour à la procédure A
    ************ Emplacement potentiel d'un START TRANSACTION ***************
    Ajoute des données dans une troisième table
    Si erreur de clé étrangère lors de l'ajout dans la seconde table -> Rollback et SIGNAL pour arrêter le déroulement
    Sinon -> Commit

    L'idéal serait que le ROLLBACK de la procédure A supprime aussi ce qui a été fait dans A si on a fait des choses dans A.

    Si j'ai bien compris, le ne peux pas placer le START TRANSACTION de A au début parce qu'il y en a potentiellement un autre imbriqué par l'appel à la procédure B ?
    Et si je le mets plus loin, après l'appel éventuel à B, le ROLLBACK de A ne va pas supprimer ce qui a été fait dans B, c'est ça ?

    Si je comprends bien l'astuce du SAVEPOINT, il faudrait le mettre en début de procédure A et un ROLLBACK TO SAVEPOINT dans A permettrait d'annuler ce qu'a COMMITé la procédure B ?
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  5. #5
    Rédacteur
    Avatar de SQLpro
    Homme Profil pro
    Expert SGBDR & SQL, spécialiste Microsoft SQL Server
    Inscrit en
    mai 2002
    Messages
    18 145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert SGBDR & SQL, spécialiste Microsoft SQL Server
    Secteur : Conseil

    Informations forums :
    Inscription : mai 2002
    Messages : 18 145
    Points : 42 447
    Points
    42 447

    Par défaut

    En fait la technique des SAVEPOINT n'a en pratique aucun intérêt.

    Cela en aurais un dans le cas d'une programmation par contrainte ou l'algorithme de backtracking ne remonterait pas jusqu'à la racine de l'arbre de décision.

    Test ce que je t'ais dit car je met en doute les propos d'Artemus…. En effet il dit :
    Par contre, il est interdit de faire cela :

    (1) --> start transaction
    (2) --> start transaction
    (2) --> commit ou rollback
    (1) --> commit ou rollback
    Cela provoque t-il une erreur ? Si oui, laquelle ???

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence * * * * *

  6. #6
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    février 2011
    Messages
    3 545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : février 2011
    Messages : 3 545
    Points : 11 071
    Points
    11 071

    Par défaut

    Salut CINPHIL.

    Voici un exemple de procédure stockée qui gère une transaction.
    J'ai créé pour l'exemple deux procédure de maj, et où je fais le passage d'une code retour afin de voir le comportement.
    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
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    --------------
    SET AUTOCOMMIT = 0
    --------------
     
    --------------
    START TRANSACTION
    --------------
     
    --------------
    DROP DATABASE IF EXISTS `base`
    --------------
     
    --------------
    CREATE DATABASE `base`
            DEFAULT CHARACTER SET `latin1`
            DEFAULT COLLATE       `latin1_general_ci`
    --------------
     
    --------------
    COMMIT
    --------------
     
    --------------
    DROP TABLE IF EXISTS `test`
    --------------
     
    --------------
    CREATE TABLE test
    ( `id`   integer unsigned NOT NULL auto_increment primary key,
      `val`  varchar(255)              default NULL
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`latin1` COLLATE=`latin1_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    DROP PROCEDURE IF EXISTS `maj1`
    --------------
     
    --------------
    CREATE PROCEDURE `maj1` (INOUT _codret integer)
    BEGIN
      insert into `test` (`val`) values ('dix'),('onze'),('douze');
     
      IF _codret <> 0 THEN
         rollback;
         SIGNAL SQLSTATE VALUE '08888' SET MESSAGE_TEXT = 'procédure "MAJ 1" rollback';
      END IF;
    END
    --------------
     
    --------------
    DROP PROCEDURE IF EXISTS `maj2`
    --------------
     
    --------------
    CREATE PROCEDURE `maj2` (INOUT _codret integer)
    BEGIN
      insert into `test` (`val`) values ('vingt'),('vingt-et-un'),('vingt-deux');
     
      IF _codret <> 0 THEN
         rollback;
         SIGNAL SQLSTATE VALUE '08888' SET MESSAGE_TEXT = 'procédure "MAJ 2" rollback';
      END IF;
    END
    --------------
     
    --------------
    DROP PROCEDURE IF EXISTS `test`
    --------------
     
    --------------
    CREATE PROCEDURE `test` (IN _maj1 integer,
                             IN _maj2 integer)
    BEGIN
      DECLARE _codret integer DEFAULT NULL;
     
      set autocommit = 0;
      start transaction;
     
      main:begin
        SET _codret = _maj1;
     
        call `maj1` (_codret);
     
        IF (_codret <> 0) THEN
           LEAVE MAIN;
        END IF;
     
        SET _codret = _maj2;
     
        call `maj2` (_codret);
     
        IF (_codret <> 0) THEN
           LEAVE MAIN;
        END IF;
     
        COMMIT;
      END main;
     
    END
    --------------
     
    --------------
    INSERT INTO test (`val`) VALUES ('un'),('deux'),('trois')
    --------------
     
    --------------
    commit
    --------------
     
    --------------
    select * from test
    --------------
     
    +----+-------+
    | id | val   |
    +----+-------+
    |  1 | un    |
    |  2 | deux  |
    |  3 | trois |
    +----+-------+
    --------------
    call test(1,0)
    --------------
     
    ERROR 1644 (08888) at line 112: procédure "MAJ 1" rollback
    --------------
    select * from test
    --------------
     
    +----+-------+
    | id | val   |
    +----+-------+
    |  1 | un    |
    |  2 | deux  |
    |  3 | trois |
    +----+-------+
    --------------
    call test(0,1)
    --------------
     
    ERROR 1644 (08888) at line 116: procédure "MAJ 2" rollback
    --------------
    select * from test
    --------------
     
    +----+-------+
    | id | val   |
    +----+-------+
    |  1 | un    |
    |  2 | deux  |
    |  3 | trois |
    +----+-------+
    --------------
    call test(0,0)
    --------------
     
    --------------
    select * from test
    --------------
     
    +----+-------------+
    | id | val         |
    +----+-------------+
    |  1 | un          |
    |  2 | deux        |
    |  3 | trois       |
    | 13 | dix         |
    | 14 | onze        |
    | 15 | douze       |
    | 16 | vingt       |
    | 17 | vingt-et-un |
    | 18 | vingt-deux  |
    +----+-------------+
     
    Appuyez sur une touche pour continuer...
    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  7. #7
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    février 2011
    Messages
    3 545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : février 2011
    Messages : 3 545
    Points : 11 071
    Points
    11 071

    Par défaut

    Salut SQLPRO.

    Est-ce que cet exemple suffit :
    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
    --------------
    SET AUTOCOMMIT = 0
    --------------
     
    --------------
    DROP DATABASE IF EXISTS `base`
    --------------
     
    --------------
    CREATE DATABASE `base`
        DEFAULT CHARACTER SET `latin1`
        DEFAULT COLLATE       `latin1_general_ci`
    --------------
     
    --------------
    DROP TABLE IF EXISTS `test`
    --------------
     
    --------------
    CREATE TABLE `test`
    ( `id`   integer  unsigned  NOT NULL auto_increment primary key,
      `lib`  varchar(255)       NOT NULL
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`latin1` COLLATE=`latin1_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    START TRANSACTION
    --------------
     
    --------------
    INSERT INTO `test` (`lib`) VALUES
      ('un'),('deux'),('trois')
    --------------
     
    --------------
    select * from `test`
    --------------
     
    +----+-------+
    | id | lib   |
    +----+-------+
    |  1 | un    |
    |  2 | deux  |
    |  3 | trois |
    +----+-------+
    --------------
    start transaction
    --------------
     
    --------------
    INSERT INTO `test` (`lib`) VALUES
      ('dix'),('onze'),('douze')
    --------------
     
    --------------
    select * from `test`
    --------------
     
    +----+-------+
    | id | lib   |
    +----+-------+
    |  1 | un    |
    |  2 | deux  |
    |  3 | trois |
    |  4 | dix   |
    |  5 | onze  |
    |  6 | douze |
    +----+-------+
    --------------
    rollback
    --------------
     
    --------------
    select * from `test`
    --------------
     
    +----+-------+
    | id | lib   |
    +----+-------+
    |  1 | un    |
    |  2 | deux  |
    |  3 | trois |
    +----+-------+
    --------------
    rollback
    --------------
     
    --------------
    select * from `test`
    --------------
     
    +----+-------+
    | id | lib   |
    +----+-------+
    |  1 | un    |
    |  2 | deux  |
    |  3 | trois |
    +----+-------+
     
    Appuyez sur une touche pour continuer...
    Le second "start transaction" se comporte comme un "commit".

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  8. #8
    Rédacteur
    Avatar de SQLpro
    Homme Profil pro
    Expert SGBDR & SQL, spécialiste Microsoft SQL Server
    Inscrit en
    mai 2002
    Messages
    18 145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert SGBDR & SQL, spécialiste Microsoft SQL Server
    Secteur : Conseil

    Informations forums :
    Inscription : mai 2002
    Messages : 18 145
    Points : 42 447
    Points
    42 447

    Par défaut

    Citation Envoyé par Artemus24 Voir le message
    Salut SQLPRO.

    Est-ce que cet exemple suffit : ...
    Oui, il est suffisant, mais montre surtout que MySQL ne sait pas gérer des transactions, car il a tout simplement "oublié" la première transaction...

    Dès qu'il y a démarrage d'une transaction explicite il doit y avoir impérativement un moyen de la valider ou de la supprimer. Or le second START TRANSACTION reporte la transaction. Au final les 3 premières lignes sont "oubliées" au niveau transactionnel et se retrouvent définitivement dans la table.
    C'est évidemment un défaut, pour ne pas dire un BUG !

    Les deux modèle transactionnels symétrique et asymétrique doivent avoir les comportement suivants...

    1) SYMÉTRIQUE

    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
    START TRANSACTION;
     
    INSERT INTO test (lib) VALUES ('un'),('deux'),('trois');
     
    select * from test;
     
    +----+-------+
    | id | lib   |
    +----+-------+
    |  1 | un    |
    |  2 | deux  |
    |  3 | trois |
    +----+-------+
     
    start transaction;
     
    INSERT INTO test (lib) VALUES ('dix'),('onze'),('douze');
     
    select * from test
     
    +----+-------+
    | id | lib   |
    +----+-------+
    |  1 | un    |
    |  2 | deux  |
    |  3 | trois |
    |  4 | dix   |
    |  5 | onze  |
    |  6 | douze |
    +----+-------+
     
    rollback;
     
    select * from test;
     
    +----+-------+
    | id | lib   |
    +----+-------+
    |  1 | un    |
    |  2 | deux  |
    |  3 | trois |
    +----+-------+
     
    rollback;
     
    select * from test;
     
    +----+-------+
    | id | lib   |
    +----+-------+
    +----+-------+

    2) ASYMÉTRIQUE

    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
    START TRANSACTION;
     
    INSERT INTO test (lib) VALUES ('un'),('deux'),('trois');
     
    select * from test;
     
    +----+-------+
    | id | lib   |
    +----+-------+
    |  1 | un    |
    |  2 | deux  |
    |  3 | trois |
    +----+-------+
     
    start transaction;
     
    INSERT INTO test (lib) VALUES ('dix'),('onze'),('douze');
     
    select * from test
     
    +----+-------+
    | id | lib   |
    +----+-------+
    |  1 | un    |
    |  2 | deux  |
    |  3 | trois |
    |  4 | dix   |
    |  5 | onze  |
    |  6 | douze |
    +----+-------+
     
    rollback;
     
    select * from test;
     
    +----+-------+
    | id | lib   |
    +----+-------+
    +----+-------+
     
    rollback;
     
    --> erreur : il n'y a pas de transaction à annuler !
    Bref encore une fois MySQL montre que c'est une grosse merde au niveau transactionnel !

    Ce que confirme Wikipedia d'ailleurs :
    popular databases like MySQL[1] do not allow nesting BEGIN - COMMIT
    Le problème c'est qu'il le permet bien, mais que ça donne un résultat faux !
    Le minimum aurait été qu'il envoie une erreur au niveau du 2e START TRANSACTION...


    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence * * * * *

  9. #9
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    février 2011
    Messages
    3 545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : février 2011
    Messages : 3 545
    Points : 11 071
    Points
    11 071

    Par défaut

    Salut SQLPRO.

    Citation Envoyé par SQLPRO
    C'est évidemment un défaut, pour ne pas dire un BUG !
    Je suis d'accord avec vous !

    Mais avec un "savepoint", on gère les transactions imbriquées !
    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
    --------------
    SET AUTOCOMMIT = 0
    --------------
     
    --------------
    START TRANSACTION
    --------------
     
    --------------
    DROP DATABASE IF EXISTS `base`
    --------------
     
    --------------
    CREATE DATABASE `base`
            DEFAULT CHARACTER SET `latin1`
            DEFAULT COLLATE       `latin1_general_ci`
    --------------
     
    --------------
    DROP TABLE IF EXISTS `test`
    --------------
     
    --------------
    CREATE TABLE test
    ( `id`   integer unsigned NOT NULL auto_increment primary key,
      `val`  varchar(255)              default NULL
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`latin1` COLLATE=`latin1_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    COMMIT
    --------------
     
    --------------
    start transaction
    --------------
     
    --------------
    insert into `test` (`val`) values ('un'),('deux'),('trois')
    --------------
     
    --------------
    select * from `test`
    --------------
     
    +----+-------+
    | id | val   |
    +----+-------+
    |  1 | un    |
    |  2 | deux  |
    |  3 | trois |
    +----+-------+
    --------------
    savepoint un
    --------------
     
    --------------
    insert into `test` (`val`) values ('dix'),('onze'),('douze')
    --------------
     
    --------------
    select * from `test`
    --------------
     
    +----+-------+
    | id | val   |
    +----+-------+
    |  1 | un    |
    |  2 | deux  |
    |  3 | trois |
    |  4 | dix   |
    |  5 | onze  |
    |  6 | douze |
    +----+-------+
    --------------
    rollback to un
    --------------
     
    --------------
    select * from `test`
    --------------
     
    +----+-------+
    | id | val   |
    +----+-------+
    |  1 | un    |
    |  2 | deux  |
    |  3 | trois |
    +----+-------+
    --------------
    savepoint deux
    --------------
     
    --------------
    insert into `test` (`val`) values ('vingt'),('vingt-et-un'),('vingt-deux')
    --------------
     
    --------------
    select * from `test`
    --------------
     
    +----+-------------+
    | id | val         |
    +----+-------------+
    |  1 | un          |
    |  2 | deux        |
    |  3 | trois       |
    |  7 | vingt       |
    |  8 | vingt-et-un |
    |  9 | vingt-deux  |
    +----+-------------+
    --------------
    rollback to deux
    --------------
     
    --------------
    select * from `test`
    --------------
     
    +----+-------+
    | id | val   |
    +----+-------+
    |  1 | un    |
    |  2 | deux  |
    |  3 | trois |
    +----+-------+
    --------------
    rollback
    --------------
     
    --------------
    select * from `test`
    --------------
     
    --------------
    COMMIT
    --------------
     
    --------------
    SET AUTOCOMMIT = 1
    --------------
     
    Appuyez sur une touche pour continuer...
    Là où j'ai un gros doute, c'est son utilisation dans une applications multitâches.

    Sinon, dans un traitement mono-utilisateur monotâche, oui, cela fonctionne mais je ne vois pas trop son intérêt.
    En fait, je n'ai jamais eu besoin jusqu'à présent du savepoint, ni non plus des transactions imbriquées.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  10. #10
    Rédacteur
    Avatar de SQLpro
    Homme Profil pro
    Expert SGBDR & SQL, spécialiste Microsoft SQL Server
    Inscrit en
    mai 2002
    Messages
    18 145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert SGBDR & SQL, spécialiste Microsoft SQL Server
    Secteur : Conseil

    Informations forums :
    Inscription : mai 2002
    Messages : 18 145
    Points : 42 447
    Points
    42 447

    Par défaut

    Citation Envoyé par Artemus24 Voir le message
    Sinon, dans un traitement mono-utilisateur monotâche, oui, cela fonctionne mais je ne vois pas trop son intérêt.
    En fait, je n'ai jamais eu besoin jusqu'à présent du savepoint, ni non plus des transactions imbriquées.

    @+
    Parce que vous n'utilisez pas les procédures stockées...

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence * * * * *

  11. #11
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    février 2011
    Messages
    3 545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : février 2011
    Messages : 3 545
    Points : 11 071
    Points
    11 071

    Par défaut

    Salut à tous.

    @ SQLPRO : c'est vrai, je ne les utilise pas.

    @ CinePhil : est-ce que mon exemple (la procédure stockée) vous convient-il ?

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  12. #12
    Modérateur
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    août 2006
    Messages
    15 856
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : août 2006
    Messages : 15 856
    Points : 31 374
    Points
    31 374
    Billets dans le blog
    4

    Par défaut

    @ CinePhil : est-ce que mon exemple (la procédure stockée) vous convient-il ?
    Je testerai ça demain en télétravail ou tout à l'heure si j'arrive à me dépêtrer d'un autre problème de modif d'un vieux programme java.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

Discussions similaires

  1. [11gR2] Portée des COMMIT et ROLLBACK dans bloc et sous-blocs
    Par ctobini dans le forum PL/SQL
    Réponses: 2
    Dernier message: 12/06/2014, 17h56
  2. Réponses: 3
    Dernier message: 01/03/2013, 10h22
  3. Réponses: 8
    Dernier message: 06/03/2008, 16h32
  4. Récupérer plusieurs lignes avec des procédures stockées
    Par GPZ{^_^} dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 12/03/2007, 13h16
  5. Tables avec des relations & procédures dynamiques
    Par JustMe dans le forum Débuter
    Réponses: 5
    Dernier message: 15/12/2004, 09h58

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