2013-02-16 2 views
1

J'utilise JDBC avec mysql. J'ai une série assez complexe d'insertions et de mises à jour que je fais en une seule transaction. Cela semble fonctionner pour la plupart, mais environ 1% du temps, je trouve que les données dans un de mes tableaux est dans un état incohérent.Une transaction fonctionne-t-elle pour les instructions sur plusieurs tables?

Je annule la transaction en cas d'erreur, mais je ne suis pas sûr de savoir comment démarrer le débogage. Ma configuration ressemble généralement à:

try { 
    conn.setAutoCommit(false); 

    PreparedStatement stmt1 = conn.prepareStatement("insert into table1"); 
    stmt1.executeUpdate(); 
    stmt1.close(); 

    PreparedStatement stmt2 = conn.prepareStatement("update table2"); 
    stmt2.executeUpdate(); 
    stmt2.close(); 

    ... more statements ... 

    conn.commit(); 
} 
catch (Exception ex) { 
    conn.rollback(); 
} 

J'utilise une version 2010 de mysql. Je pourrais essayer de mettre à jour cela, mais j'ai l'impression que c'est plus quelque chose dans mon code d'application qui cause l'incohérence.

Y a-t-il des outils de débogage que je pourrais trouver utiles au niveau de la base de données pour vous aider? D'autres pointeurs? J'utilise JDBC avec tous les paramètres par défaut, je me demande s'il y a un niveau de transaction plus stricte que je dois utiliser pour ce genre de scénario?

Merci

----- ----- Remarque Tous mes tableaux sont InnoDB.

+1

La première chose que vous devez vérifier est si vous utilisez MyISAM ou InnoDB. MyISAM ne supporte pas les transactions. – nos

+0

Confirmé toutes mes tables sont InnoDb. – user291701

+0

niveau de transaction lecture validée? – Sebas

Répondre

0

Hm .. Intéressant. Oui, ça devrait marcher. Etes-vous sûr que ce n'est pas vous qui produisez l'incohérence (quoi que cela signifie ici, vous ne l'avez pas spécifié)? En insérant/mettant à jour de mauvaises choses? :-)

Juste une idée - nous avons rencontré cela plusieurs fois. Deadlock se résolvant. Les serveurs DB utilisés pour gérer cela. Le risque de blocage est plus élevé si vous avez plusieurs threads parallèles et que les blocs de transaction manipulent plus de tables. Dans ce cas, certaines de vos transactions pourraient être interrompues (et annulées) par le serveur de base de données lui-même. Et ces transactions entraîneront une erreur.

Le code que vous avez écrit ci-dessus ne fait que reculer dans le cas d'exception (la transaction avortée a déjà été annulée, donc elle n'en fait pas trop), mais avez-vous essayé d'imprimer/enregistrer les exceptions? Si non, vous devriez.

Bien sûr, les transactions sont séparées les unes des autres. Mais cela pourrait expliquer pourquoi vous rencontrez ce comportement étrange dans seulement 1-2% des cas ...

Vous devriez aussi consulter les logs de votre serveur mysql. Il est également possible que le serveur lui-même échoue pour une raison quelconque. Et encore un conseil: vous pouvez essayer de lancer "mysqltop" (ou "mtop", j'espère que je me souviendrai du nom de cet outil correctement ..). Ceci est capable de surveiller et de vous montrer ce qui se passe à l'intérieur du serveur de base de données. Cependant, il est principalement utilisé pour suivre les performances de nos sqls, cela montre également des échecs. Peut-être que cela pourrait aussi vous aider ...

+0

Oui, il est probable que quelque chose dans mon code de l'application, je suis en train de déboguer plus loin pour essayer d'attraper ce qui se passe. Au moins, j'ai maintenant quelques vérifications de base à la suite de ce post (InnoDB devrait être ok, etc). – user291701

0

Peut-être que vous utilisez DDL (créer une table, modifier une table, etc.) dans vos instructions?

Je ne suis pas sûr de MySQL mais il ne sera peut-être pas capable de restaurer les instructions DDL.

Par exemple:

  • PostgreSQL peut rollback DDL,
  • Oracle effectue commit avant d'exécuter DDL.

Voir ici: http://dev.mysql.com/doc/refman/5.0/en/cannot-roll-back.html

+0

Merci, je ne crée pas de tables dans mes transactions - je devrais être ok ici alors? – user291701

+0

Oui, ça devrait aller. Une autre idée pourrait être qu'un autre processus accède à la même connexion et effectue un commit simultanément ... – Grzegorz

Questions connexes