2008-11-14 9 views
5

Parece que la forma clásica de manejar transacciones con JDBC es establecer el autocompromiso en falso. Esto crea una nueva transacción, y cada llamada para confirmar marca el comienzo de las siguientes transacciones. En la aplicación de subprocesos múltiples, entiendo que es una práctica común abrir una nueva conexión para cada subproceso.JDBC: ¿Puedo compartir una conexión en una aplicación multihilo y disfrutar de buenas transacciones?

Estoy escribiendo una aplicación de servidor multi-cliente basada en RMI, de modo que, básicamente, mi servidor está generando un hilo por cada conexión nueva. Para manejar las transacciones correctamente ¿debo ir y crear una nueva conexión para cada uno de esos subprocesos? ¿No es prohibitivo el costo de tal arquitectura?

Respuesta

4

Sí, en general, necesita crear una nueva conexión para cada hilo. Usted no tiene control sobre cómo el sistema operativo veces la ejecución de los hilos (a pesar de definir sus propias secciones críticas), por lo que podría tener varios subprocesos tratando de enviar datos por ese conducto.

Tenga en cuenta lo mismo se aplica a las comunicaciones de red. Si tuviera dos hilos tratando de compartir un socket con una conexión HTTP, por ejemplo.

  • Tema 1 hace una petición
  • Tema 2 hace una petición
  • Tema 1 lee bytes de la toma, sin saberlo, la lectura de la respuesta a partir de hilos de 2 petición

Si envuelto todas sus transacciones en secciones críticas y, por lo tanto, bloquear cualquier otro subproceso para un ciclo completo de inicio/confirmación, entonces es posible que pueda compartir una conexión de base de datos entre subprocesos. Pero no lo haría incluso entonces, a menos que realmente tenga un conocimiento innato del protocolo JDBC.

Si la mayoría de sus subprocesos tienen poca necesidad de conexiones a la base de datos (o ninguna), puede designar un subproceso para hacer su trabajo de base de datos, y tener otros subprocesos en cola para un solo subproceso. Eso reduciría la sobrecarga de tantas conexiones. Pero tendrá que descubrir cómo administrar las conexiones por hilo en su entorno (o hacer otra pregunta específica sobre eso en StackOverflow).

update: Para responder a su pregunta en el comentario, la mayoría de las marcas de bases de datos no admiten múltiples transacciones simultáneas en una sola conexión (InterBase/Firebird es la única excepción que conozco).

Sería bueno tener un objeto de transacción por separado, y poder iniciar y confirmar transacciones múltiples por conexión. Pero los proveedores simplemente no lo admiten.

Del mismo modo, API estándar independientes del proveedor como JDBC y ODBC hacen la misma suposición, que el estado de la transacción es simplemente una propiedad del objeto de conexión.

+0

Ok ... Solo por curiosidad, ¿tienes una idea de por qué la definición de la transacción es eso junto con la definición de conexión en JDBC? Realmente apreciaría un objeto de transacción. – fulmicoton

+0

¡Muchas gracias por su respuesta! – fulmicoton

+1

La afirmación "podría inadvertidamente tener varios subprocesos intentando enviar datos por ese conducto" en esta respuesta es definitivamente incorrecta para postgresql. Ver http://doc.postgresintl.com/jdbc/ch10.html. La conexión es al menos segura para subprocesos, aunque no completamente paralelizada como podría ser. –

1

Es una práctica poco común abrir una nueva conexión para cada hilo. Por lo general, utiliza un grupo de conexiones como c3po biblioteca.

Si se encuentra en un servidor de aplicaciones o utiliza Hibernate, por ejemplo, consulte la documentación y encontrará cómo configurar el grupo de conexiones.

+0

Gracias por su contribución. Debería estar bien sin un grupo de conexiones en mi caso: no es muy probable que solicite conexiones con demasiada frecuencia de todos modos. Para otros lectores: Estoy bastante seguro de que c3po es una gran biblioteca, sin embargo, asegúrese de que está bien que use LGPL. – fulmicoton

+0

¿Cuál es el problema con LGPL? Puede usarlo con aplicaciones comerciales (es Lesser GPL). –

1

El mismo objeto de conexión se puede usar para crear múltiples objetos de declaración y estos objetos de declaración pueden ser utilizados por diferentes subprocesos al mismo tiempo.La mayoría de los DB modernos interconectados por JDBC pueden hacer eso. El JDBC puede así hacer uso de cursores concurrentes de la siguiente manera. PostgreSQL no es una excepción, véase por ejemplo:

http://doc.postgresintl.com/jdbc/ch10.html

Esto permite la agrupación de conexiones donde la conexión se utilizan solamente por un corto tiempo, a saber, creó el objeto de declaración y después de eso, pero regresó a la piscina. Este agrupamiento a corto plazo solo se recomienda cuando la conexión JDBC también realiza la paralelización de las operaciones de declaración; de lo contrario, la agrupación normal de conexiones podría mostrar mejores resultados. De todos modos, el hilo puede continuar trabajando con el objeto de declaración y cerrarlo más tarde, pero no la conexión.

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 

Lo anterior sólo funciona en automático modalidad de confirmación. Si se necesitan transacciones, aún no es necesario vincular la transacción a un hilo. Solo puede dividir el agrupamiento a lo largo de las transacciones y usar el mismo enfoque que el anterior. Pero esto solo es necesario no debido a alguna limitación de conexión de socket, sino porque el JDBC luego iguala la ID de la sesión con la ID de la transacción.

Si mal no recuerdo, debería haber API y productos con un diseño menos simple, donde el ID de sesión y el ID de transacción no se equiparan. En esta API puede escribir su servidor con un único objeto de conexión de base de datos, incluso cuando realiza transacciones . Tendrá que verificar y decirle más tarde qué son estas API y productos.

Cuestiones relacionadas