Il semble que la manière classique de gérer les transactions avec JDBC consiste à définir la validation automatique sur false. Cela crée une nouvelle transaction et chaque appel à valider marque le début des transactions suivantes. Sur l'application multithread, je comprends qu'il est de pratique courante d'ouvrir une nouvelle connexion pour chaque thread. Je suis en train d'écrire une application serveur multi-client basée sur RMI, de sorte que mon serveur génère essentiellement un thread pour chaque nouvelle connexion. Pour gérer correctement les transactions, dois-je créer une nouvelle connexion pour chacun de ces threads? Le coût d'une telle architecture n'est-il pas prohibitif?JDBC: Puis-je partager une connexion dans une application multithread et profiter de bonnes transactions?
Répondre
Oui, en général, vous devez créer une nouvelle connexion pour chaque thread. Vous n'avez aucun contrôle sur la façon dont le système d'exploitation exécute les délais d'exécution des threads (bien que vous définissiez vos propres sections critiques), de sorte que vous pourriez avoir plusieurs threads essayant d'envoyer des données par le biais de ce canal.
Notez qu'il en va de même pour toutes les communications réseau. Si vous aviez deux threads essayant de partager un socket avec une connexion HTTP, par exemple.
- Discussion 1 fait une demande
- Discussion 2 fait une demande
- Discussion 1 lit octets de la prise, la lecture à son insu la réponse de la demande de fil 2
Si vous enveloppé toutes vos transactions dans les sections critiques, et par conséquent verrouiller tous les autres threads pour un cycle entier begin/commit, vous pouvez alors partager une connexion de base de données entre threads. Mais je ne le ferais pas encore, à moins d'avoir une connaissance innée du protocole JDBC. Si la plupart de vos threads ont rarement besoin de connexions à la base de données (ou pas du tout), vous pouvez désigner un thread pour que votre base de données fonctionne et que d'autres threads placent leurs requêtes dans ce thread. Cela réduirait les frais généraux de tant de connexions. Mais vous devrez trouver comment gérer les connexions par thread dans votre environnement (ou poser une question spécifique à propos de StackOverflow). Pour répondre à votre question dans le commentaire, la plupart des marques de bases de données ne prennent pas en charge plusieurs transactions simultanées sur une même connexion (InterBase/Firebird est la seule exception que je connaisse).
Ce serait bien d'avoir un objet de transaction séparé, et de pouvoir démarrer et valider plusieurs transactions par connexion. Mais les vendeurs ne le supportent tout simplement pas.
De même, les API standard indépendantes du fournisseur comme JDBC et ODBC font la même hypothèse, cet état de transaction est simplement une propriété de l'objet de connexion.
Il est inhabituel d'ouvrir une nouvelle connexion pour chaque thread. Généralement, vous utilisez un pool de connexions tel que c3po.
Si vous utilisez un serveur d'applications ou que vous utilisez Hibernate par exemple, consultez la documentation et vous trouverez comment configurer le pool de connexions.
Merci pour votre contribution. Je devrais être ok sans un pool de connexion dans mon cas: je ne suis pas très susceptible de demander des connexions trop souvent de toute façon. Pour l'autre lecteur: Je suis sûr que c3po est une excellente bibliothèque, mais assurez-vous que vous pouvez utiliser la LGPL. – fulmicoton
Quel est le problème avec LGPL? Vous pouvez l'utiliser avec des applications commerciales (c'est moins GPL). –
Le même objet de connexion peut être utilisé pour créer plusieurs objets d'instructions et ces objets d'instruction peuvent ensuite être utilisés par des threads différents simultanément.La plupart des DB modernes interfacées avec JDBC peuvent le faire. Le JDBC est ainsi capable d'utiliser des curseurs concurrents comme suit. PostgreSQL ne fait pas exception, voir par exemple:
http://doc.postgresintl.com/jdbc/ch10.html
Cela permet la mise en commun de connexion où sont utilisés uniquement la connexion pour un court laps de temps, à savoir créer l'objet de déclaration et mais après retourné à la piscine. Cette mise en pool de courte durée est recommandée uniquement lorsque la connexion JDBC effectue également la parallélisation des opérations d'instruction, sinon le regroupement de connexions normal peut donner de meilleurs résultats. De toute façon, le thread peut continuer à travailler avec l'objet statement et le fermer plus tard, mais pas la connexion.
1. Thread 1 opens statement
3. Thread 2 opens statement
4. Thread 1 does something Thread 2 does something
5. ... ...
6. Thread 1 closes statement ...
7. Thread 2 closes statement
Ce qui précède fonctionne uniquement en mode de validation automatique. Si des transactions sont nécessaires, il n'est pas nécessaire de lier la transaction à un thread. Vous pouvez simplement partitionner le pooling le long des transactions et utiliser la même approche que ci-dessus. Mais ceci n'est nécessaire qu'en raison d'une limitation de connexion de socket, mais parce que le JDBC assimile alors l'ID de session à l'ID de transaction. Si je me souviens bien, il devrait y avoir des API et des produits avec une conception moins simpliste, où l'ID de session et l'ID de transaction ne sont pas assimilés. Dans cette API, vous pouvez écrire votre serveur avec un objet de connexion de base de données unique, même s'il effectue des transactions . Devra vérifier et vous dire plus tard ce que sont ces API et produits.
Ok ... Juste par curiosité, avez-vous une idée de la raison pour laquelle la définition de la transaction est associée à la définition de la connexion sur JDBC? J'apprécierais vraiment un objet de transaction. – fulmicoton
Merci beaucoup pour votre réponse !!! – fulmicoton
La déclaration "vous pourriez avoir par inadvertance plusieurs threads essayant d'envoyer des données vers le bas de cette pipe" dans cette réponse est définitivement fausse pour postgresql. Voir http://doc.postgresintl.com/jdbc/ch10.html. La connexion est au moins thread-safe, mais pas entièrement parallélisé comme il pourrait l'être. –