PDA

Ver la Versión Completa : Como usar dbExpress en hilos ?


rolandoj
21-02-2008, 16:22:54
Hola,

Estoy trabajando con Delphi 2007 Update 3 y dbExpress.

Mi aplicación maneja hilos y mi problema actual es que, cuando entra a un segundo hilo en paralelo, la aplicación se bloquea al intentar abrir una segunda conexión a la Base de Datos.

Mi pregunta entonces es : Como se utiliza dbExpress en una aplicación con hilos ?. He estado buscando y no he encontrado una explicación clara. No sé si el problema es con drivers o si es que dbExpress en hilos no se maneja como lo estoy haciendo.

Veamos lo que hago y lo que he analizado:

Yo estoy usando un Data Module para tener mi componente TSQLConnection. Cada vez que se crea un hilo, el programa crea un nuevo Data Module de esa clase y abre una nueva conexión a la base de Datos, usando el mismos usuario.

Ya verifiqué que el bloqueo se produce justo al tratar de abrir la segunda conexión; no se trata por tanto de colisiones en la ejecución de comandos SQL.

Ya probé, con un pequeño programa secuencial, que dbExpress si es capaz de abrir una segunda conexión a la Base de Datos, en un segundo componente, usando el mismo usuario.

En este punto, lo que sospecho es que el bloqueo se produce cuando se intenta abrir la base de datos y el primer componente está enviando un requerimiento al motor SQL, o recuperando datos de la misma. Si estoy en lo cierto, supongo que eso significa que, o hay un error, o hay que usar un solo componente para todos los hilos, lo que me sorprendería bastante.

Alguién puede ilustrar el tema, o confirmar que hay falla ?

jachguate
21-02-2008, 18:40:14
¿contra que base de datos estas conectando?
¿es el driver que usas thread-safe?

Hasta luego.

;)

rolandoj
21-02-2008, 20:22:50
¿contra que base de datos estas conectando?
¿es el driver que usas thread-safe?

Hasta luego.

;)
Hola,

Muchas gracias por responder.

En este momento estoy usando Interbase 6 y el driver dbExpress que viene con Delphi 2007 Update 3, o sea dbxint30.dll.

Debo anotar que, aunque esto puede ser parte del problema, me interesa fundamentalmente la parte conceptual de como debe hacerse, en primer lugar porque este es un ambiente de pruebas preliminares; en pocos días, empezarán las pruebas con Oracle 10g, y para ese entonces, debo tener claro como es el mecanismo.

Por otra parte, no debe quedar ningún código dependiente del motor; algo que siempre me ha funcionado sin problemas con el BDE y es una premisa de portabilidad básica en todas mis aplicaciones.

jachguate
21-02-2008, 22:31:19
En este momento estoy usando Interbase 6 y el driver dbExpress que viene con Delphi 2007 Update 3, o sea dbxint30.dll.
Uf... en los tiempos de interbase 6 yo todavía no hacía aplicaciones multihilo, pero es probable que firebird heredara de allí una limitante:

El protocolo local no soporta multihilos.

Eso te obliga a forzar una conexión por el protocolo de red, por ejemplo, añadiendo localhost o 127.0.0.1 como host de la cadena de conexión. Por ejemplo:

localhost:c:\datos\basededatos

en lugar de

c:\datos\basededatos

Hasta luego.

;)

rolandoj
21-02-2008, 22:48:41
Uf... en los tiempos de interbase 6 yo todavía no hacía aplicaciones multihilo, pero es probable que firebird heredara de allí una limitante:

El protocolo local no soporta multihilos.

Eso te obliga a forzar una conexión por el protocolo de red, por ejemplo, añadiendo localhost o 127.0.0.1 como host de la cadena de conexión. Por ejemplo:

localhost:c:\datos\basededatos

en lugar de

c:\datos\basededatos

Hasta luego.

;)
Hola,

Muchas gracias por la respuesta. Tecnicamente muy interesante y una de las mejores que he recibido en mis preguntas al foro. Me recuerda un problema que se presenta en la configuración del BDE donde a veces es necesario probar diferentes notaciones para indicar caminos de red, y a otro muy similar que de paso experimentamos hace poco, no solo con los aplicativos Delphi, sino con una red en general donde, debido a problemas en la configuración general, por un tiempo fué necesario indicar en los clientes la dirección IP, en lugar del nombre de equipo en la red que debía accederse.

En este momento estoy donde otro cliente; pero creo que mañana podré probar la solución que planteas. Te tendré al tanto.

Muchos saludos

rolandoj
22-02-2008, 17:26:12
Uf... en los tiempos de interbase 6 yo todavía no hacía aplicaciones multihilo, pero es probable que firebird heredara de allí una limitante:

El protocolo local no soporta multihilos.

Eso te obliga a forzar una conexión por el protocolo de red, por ejemplo, añadiendo localhost o 127.0.0.1 como host de la cadena de conexión. Por ejemplo:

localhost:c:\datos\basededatos

en lugar de

c:\datos\basededatos

Hasta luego.

;)
Hola jachguate,

Una vez más, muchas gracias por la ayuda.

Hoy probamos y aunque no se solucionó totalmente, si hubo mejora y no hay duda que es el camino correcto. Veamos:

Excepto en una de las pruebas, en la que uno de los clientes quedó bloqueado, no se presentaron más bloqueos; pero, normalmente, solo a uno de los clientes le devolvía la respuesta correcta. Al otro cliente se le devolvía el siguiente mensaje de error :

"Error writing data to the connection"

Una investigación de ese error en Internet indica varias causas; pero, en este caso, la más probable es un problema con el software cliente de Interbase, que según encontré en algunas notas muy antiguas, no es hilo seguro en versiones anteriores a la 7.

Me queda una gran duda:

dbExpress usa su propio driver cliente "dbxint30.dll" para conectarse, y más nada. Puesto que este es todo el cliente y es la última versión, yo suponía que era un hilo seguro, y por eso, inicialmente no lo había verificado. No encuentro lógico que a estas alturas de la historia no lo sea.

Una posible explicación es que falle al tratarse de una conexión a una versión antigua de la base de datos; pero no debería haber mucha diferencia entre ese manejo para una versión anterior y la de la versión actual, por lo que no me es muy convincente que excluyeran esa capacidad.

Investigué en Internet y no pude encontrar nada que afirmara, o rechazara, el hecho de que ese driver sea un hilo seguro. En cambio, encontré una nota de Agosto del 2007 en que alguién expresaba dudas en que la creación de la conexión dbExpress fuera hilo seguro, y varias notas confirmando que mi metodología de acceso (crear una nueva conexión para cada hilo) es la correcta con dbExpress.

Todo esto, unido otra serie de errores y problemas, que he venido encontrando al avanzar con dbExpress, me tiene bastante intranquilo.

En últimas, la aplicación correra contra Oracle 10, donde yo esperaría que esto se arreglara; pero, abusando de tú gentileza, mucho agradecería toda la documentación a que pudieras remitirme, y comentarios con los que pudieras ilustrar el tema y / o anticipar posibles problemas.

Muchos saludos

jachguate
22-02-2008, 17:59:10
Hola.

Como te he comentado, nunca intenté hacer una conexión multi-hilo a interbase, en ninguna versión.

Creo que para efectos de pruebas, y para comproabar que el problema no está en dbExpress, podes valerte de realizar exactamente la misma prueba, pero sobre firebird, lo que no implica mucho mas que, hacer un backup de la base de datos, desinstalar interbase, instalar firebird con soporte para "legacy applications", restaurar el backup y realizar la prueba.

Una investigación de ese error en Internet indica varias causas; pero, en este caso, la más probable es un problema con el software cliente de Interbase, que según encontré en algunas notas muy antiguas, no es hilo seguro en versiones anteriores a la 7.

Me queda una gran duda:

dbExpress usa su propio driver cliente "dbxint30.dll" para conectarse, y más nada. Puesto que este es todo el cliente y es la última versión, yo suponía que era un hilo seguro, y por eso, inicialmente no lo había verificado. No encuentro lógico que a estas alturas de la historia no lo sea.

El driver de dbExpress (dbxInt30.dll) no hará mas que conectarse al cliente de interbase (gds32.dll). Por tanto, para que funcione, es necesario que ambos sean thread-safe.

Una posible explicación es que falle al tratarse de una conexión a una versión antigua de la base de datos; pero no debería haber mucha diferencia entre ese manejo para una versión anterior y la de la versión actual, por lo que no me es muy convincente que excluyeran esa capacidad.
¡Claro que puede haberla!
Quizás el equipo de desarrollo de interbase no se planteó la necesidad de soportar multiples conexiones concurrentes desde una misma aplicación y por tanto desde una única instancia del cliente, hasta muy tarde, y no lograron completar el trabajo hasta después de la v. 6.0.

Investigué en Internet y no pude encontrar nada que afirmara, o rechazara, el hecho de que ese driver sea un hilo seguro. En cambio, encontré una nota de Agosto del 2007 en que alguién expresaba dudas en que la creación de la conexión dbExpress fuera hilo seguro, y varias notas confirmando que mi metodología de acceso (crear una nueva conexión para cada hilo) es la correcta con dbExpress.

No uso dbExpress, pero francamente dudo que a estas alturas, como motor, no tuviera esa capacidad. Otro asunto son los drivers, pero como ya te dije antes, no está muy difícil comprobarlo.

Finalmente, puedo garantizar que el cliente de firebird 1.5 y superiores se desempeñan muy bien en entornos multihilos. En ocasiones esporádicas, las aplicaciones que usan esa característica han presentado algun problema que de primera mano atribuyo al cliente, pero que no he logrado comprobar.

En mi caso, las conexiones las hago usando IBX como capa de conexión.

Hasta luego.

;)

rolandoj
05-03-2008, 21:12:32
Hola jachguate,

Perdón por la demora. Estaba ocupado con má proyectos y otros aspectos de este.

Estaba esperando Oracle para probar; pero como se ha demorado el conseguírlo, en el primer tiempo libre, he hecho unas pruebas preliminares con Firebird 2.0.3

Estas pruebas han fracasado, lo que me tiene bastante preocupado. Pienso elaborar unas pruebas independientes para descartar posibles errores de aplicación que puedan haberse introducido con la migración a Delphi 2007.

Mientras tanto, como mencionas que a veces hay fallas que atribuyes al cliente, podrías comentar más detalles al respecto ?

Hay otro punto que me preocupa:

El hilo de donde viene cada evento que accesa la base de datos es uno que yo no he creado. Se supone que es generado automáticamente cuando el Servidor invoca la librería ISAPI que maneja los eventos del caso, y por tanto, en todo momento he estado suponiendo que es seguro; pero, a estas alturas, y después de numerosos problemas con delphi 2007, ya desconfío de todo. Has usado esa tecnología ?.

Por la misma razón anterior, creo que no sobra comentar lo siguiente:

El manejo de hilos bajo ISAPI (y en general), hasta donde sé, parte de no usar variable globales (típicamente, todas las variables tienen su origen dentro de la rutina que se invoca en el hilo), o si se necesitan, hay que proteger cualquier acceso a ellas mediante secciones críticas.

Todo el código está basado en ese principio. Hay algo adicional que creas que se deba tener en cuenta ?

Gracias de antemano por cualquier ayuda