web-dev-qa-db-fra.com

Pourquoi ai-je besoin de Transaction dans Hibernate pour les opérations en lecture seule?

Pourquoi ai-je besoin de Transaction dans Hibernate pour les opérations en lecture seule?

La transaction suivante verrouille-t-elle la base de données?

Exemple de code à extraire de la base de données:

Transaction tx = HibernateUtil.getCurrentSession().beginTransaction(); // why begin transaction?
//readonly operation here

tx.commit() // why tx.commit? I don't want to write anything

Puis-je utiliser session.close() au lieu de tx.commit()?

91
user93796

Vous avez peut-être des raisons de marquer les transactions en lecture seule.

  1. Les transactions pour la lecture peuvent sembler étranges et souvent, les gens ne marquent pas les méthodes pour les transactions dans ce cas. Mais JDBC créera une transaction de toute façon, il travaillera simplement dans autocommit=true Si une option différente n’a pas été définie explicitement.
  2. Cependant, rien ne garantit que votre méthode n'écrit pas dans la base de données. Si vous marquez la méthode en tant que @Transactional(readonly=true), Spring définira la transaction JDBC en mode lecture seule. Ainsi, vous dicterez s'il est réellement possible d'écrire dans la base de données dans le cadre de cette transaction. Si votre architecture est lourde et que certains membres de l'équipe peuvent choisir de placer une requête de modification là où elle n'est pas attendue, cet indicateur vous pointera vers l'emplacement problématique.
  3. Les transactions en lecture seule peuvent également être optimisées par les bases de données, mais ceci est bien sûr spécifique à la base de données. Par exemple. MySQL a ajouté le support pour cela uniquement dans InnoDB à partir de la version 5.6.4.
  4. Si vous n'utilisez pas JDBC directement, mais plutôt un ORM, cela pourrait être problématique. Par exemple, la communauté Hibernate affirme que travailler en dehors d'une transaction peut entraîner un comportement imprévisible. En effet, Hibernate ouvrira la transaction, mais ne la fermera pas d'elle-même. Par conséquent, la connexion sera renvoyée au pool de connexions sans que la transaction soit validée. Qu'est-ce qui se passe ensuite? JDBC garde le silence, il s’agit donc d’une implémentation spécifique (MySQL annule la transaction, Oracle l’engage). Cela peut également être configuré au niveau du pool de connexions (par exemple, C3P0 vous donne une telle option, la restauration par défaut).
  5. Une autre chose en ce qui concerne Hibernate, Spring définit le FlushMode sur MANUAL dans le cas de transactions en lecture seule, ce qui conduit à d’autres optimisations telles que l’absence de vérification à blanc.
  6. Vous souhaiterez peut-être remplacer ou définir explicitement le niveau d'isolation de la transaction. Cela a également un impact sur les transactions en lecture puisque vous faites ou ne voulez pas lire les modifications non validées, être exposé à des lectures fantômes, etc.

En résumé, vous pouvez aller dans les deux sens, mais vous devez comprendre les conséquences.

118

Toutes les instructions de base de données sont exécutées dans le contexte d’une transaction physique, même si nous ne déclarons pas explicitement les limites de la transaction (BEGIN/COMMIT/ROLLBACK).

Si vous ne déclarez pas explicitement les limites des transactions, chaque instruction devra être exécutée dans une transaction distincte (mode autocommit.). Cela peut même conduire à ouvrir et fermer une connexion par instruction à moins que votre environnement ne puisse gérer la liaison connexion par thread.

Déclarer un service en tant que @Transactional vous donnera une connexion pour toute la durée de la transaction et toutes les instructions utiliseront cette connexion d'isolation unique. C'est bien mieux que de ne pas utiliser des transactions explicites en premier lieu.

Sur les applications volumineuses, vous pouvez avoir plusieurs demandes simultanées et réduire le taux de demande d'acquisition de connexion à une base de données va certainement améliorer les performances globales de votre application.

JPA n'applique pas les transactions sur les opérations de lecture. Seules les écritures génèrent une exception de transaction requise au cas où vous oublieriez de commencer un contexte transactionnel. Néanmoins, il est toujours préférable de déclarer les limites des transactions, même pour les transactions en lecture seule (in Spring @Transactional vous permet de marquer les transactions en lecture seule, ce qui présente un avantage considérable en termes de performances).

35
Vlad Mihalcea

Les transactions mettent en effet des verrous sur la base de données - de bons moteurs de base de données traitent les verrous concurrents de manière judicieuse - et sont utiles en lecture seule pour garantir qu'aucune transaction autre ajoute des données rendant votre vue incohérente. Vous voulez toujours une transaction (bien qu'il soit parfois raisonnable de régler le niveau d'isolation, il est préférable de ne pas le faire pour commencer); si vous n'écrivez jamais dans la base de données lors de votre transaction, valider et annuler la transaction est identique (et très économique).

Désormais, si vous avez de la chance et que vos requêtes sur la base de données sont telles que l'ORM les mappe toujours à des requêtes SQL uniques, vous pouvez vous échapper sans transaction explicite, en vous basant sur le comportement autocommit intégré de la base de données. , mais les ORM sont des systèmes relativement complexes et il n’est donc pas prudent de s’appuyer sur un tel comportement, à moins que vous ne travailliez beaucoup plus pour vérifier ce que fait réellement l’implémentation. Il est beaucoup plus facile d’écrire les limites des transactions explicites (surtout si vous pouvez le faire avec AOP ou une technique similaire pilotée par ORM; à partir de Java 7 versions ultérieures peuvent être utilisées) aussi je suppose).

16
Donal Fellows

Peu importe que vous lisiez ou non - la base de données doit toujours garder une trace de votre jeu de résultats, car d'autres clients de la base de données peuvent vouloir écrire des données susceptibles de modifier votre jeu de résultats.

J'ai vu des programmes défectueux tuer de gros systèmes de base de données, car ils ne lisaient que des données, mais ne commettaient jamais, ce qui obligeait le journal des transactions à croître, car la base de données ne peut pas publier les données de transaction avant COMMIT ou ROLLBACK, même si le client n'a rien fait. Pendant des heures.

13
Ingo