Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Conexión con bases de datos
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Conexión con bases de datos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 29-01-2008
Avatar de Ivanzinho
[Ivanzinho] Ivanzinho is offline
Miembro Premium
 
Registrado: ene 2005
Ubicación: Galicia
Posts: 595
Poder: 20
Ivanzinho Va por buen camino
Funcionamiento de IBX y FIBPlus

Hola compañeros, les planteo una duda en base al funcionamiento de los componentes de acceso a datos IBX.

Estuve realizando pruebas de velocidad y concurrencia con componentes IBX y FIBPlus con una base de datos Firebird 2.0. Para esto realicé inserciones masivas en una tabla de la base de datos desde una aplicación realizada en Delphi 5 con el fin de determinar cuál de los componentes era más rápido y comprobar que en caso de producirse alguna colisión (violación de clave primaria), el programa lo detectase y continuase su ejecución. Cabe destacar también que las claves de los registros insertados deben ser consecutivas y que no puede haber saltos por el medio.

Las prueba se realizaron ejecutando la aplicación concurrentemente desde tres equipos distintos, que apuntaban a la misma B.D., durante 30 seg. y en diez ocasiones distintas para luego calcular la media de inserciones y colisiones. El código de los distintos procedimientos que utilizan en la inserción son los siguientes :

Rutina inserción y control de errores :
Código Delphi [-]
seguir := trae;
//mientras no termine la transacción correctamente o no se pueda resolver la excepción
while seguir do
  try
    dmDatos.StartTransaction;
    dmDatos.IBDSMovimientos.Insert;
    dmDatos.IBDSMovimientos.Post;
    dmDatos.Commit;
    seguir := false;
    AbrirTablas(false, 0,0); 
  except 
    dmDatos.Rollback;
    //Control de errores  
  end;

En el data module nos encontramos con los siguientes procedimientos :
Código Delphi [-]
//Inserción del registro, carga de datos por defecto
procedure TDMDatos.IBDSMovimientosAfterInsert(DataSet: TDataSet);
begin
  IBDsMovimientosNum_mr.Value := -1;
  IBDsMovimientosAno_mr.Value := Ano;
  IBDsMovimientosFgr_mr.Value := date;
  IBDsMovimientosRev_mr.Value := 0;
end;

procedure TDMDatos.StartTransaction;
begin
  if not IBTrFac.InTransaction then
    IBTrFac.StartTransaction; 
end;

procedure TDMDatos.Commit;
begin
  if IBTrFac.InTransaction then
    IBTrFac.Commit;
end;

procedure TDMDatos.Rollback;
begin
  if IBTrFac.InTransaction then
    IBTrFac.Rollback;
end;
NOTA : Con los componentes FIBPlus no hace falta comprobar la si la conexión está activa, lo hacen los componentes automáticamente, lo que no se es si se continúa con la transacción activa o se aborta y crea una nueva.

En la base de datos tenemos el siguiente trigger que es donde se calcula la clave primaria.
Código SQL [-]
CREATE trigger mbmovimientosrect_bi_actclave for mbmovimientosrect
active before insert position 0
AS
  declare variable v_clave integer;
begin
  Select max(Num_mr)
  from mbmovimientosrect
  where ano_mr = new.ano_mr
  into :v_clave;

  if (v_clave is null) then
    v_clave = 1;
  else
    v_clave = v_clave + 1;

   new.num_mr = v_clave;
end

Tras cada inserción masiva realizo un borrado de los registros de la base de datos, desde el IBExpert con una simple consulta delete from tabla para iniciar otra nueva inserción masiva. Con FIBPlus todo funciona correctamente, los registros se empiezan a insertar desde el 1, en cambio con IBX los registros se comienzan a insertar desde el último registro almacenado en el DataSet de la aplicación. Para que esto no suceda tuve que realizar un rollback antes de comenzar la transacción en el procedimiento de inserción. Este comportamiento me resulta sumamente extraño, ya que el calculo de la clave se realiza en un trigger fuera de la aplicación.

También probé a realizar la inserción desde otra transacción, pero el resultado era el mismo :
Código Delphi [-]
 Seguir := trae;
T := TIBTransaction.Create(nil);
  try
    T.DefaultDatabase := DMDatos.IBDBfac;

    Q := TIBSQL.Create(nil);
    try
      Q.Database := DMDatos.IBDBfac;
      Q.Transaction := DMDatos.IBTrFac;
      Q.SQL.Add('Insert into mbMovimientosRect(Num_mr, Ano_mr, Fgr_mr, Rev_mr)');
      Q.SQL.Add('Values(-1, :Ano, :Fecha, 0)');

      Q.Params.ByName('Ano').AsInteger := Ano;
      Q.Params.ByName('Fecha').AsDate := Now;

      while seguir do
        try
          T.StartTransaction;
          Q.ExecQuery;
          T.Commit;
          Seguir := false;
          DMDatos.Rollback;
          AbrirTablas
        except 
          //Control de errores
        end;
    finally
      Q.Free;
    end;
  finally
    T.Free;
  end;

Si has llegado hasta aquí te lo agradezco, pues he soltado un buen rollo . Mi pregunta es si alguien me puede decir a que se debe este comportamiento, ya que puede haber características importantes de IBX que desconozca.

Como nota de interés hay que decir que los resultados fueron mejores con FIBPlus, mayor velocidad en las inserciones y menor número de colisiones, pero los resultados obtenidos con IBX tampoco eran malos, por lo que en principio no compensa el desembolso económico que hay que realizar para adquirir los componentes FIB (a no ser que alguno de vosotros me de una razón para pensar lo contrario).

Un saúdo y muchas gracias por vuestra atención
__________________
Si no lees esto no vivirás tranquilo
Non lle poñades chatas â obra namentras non se remata. O que pense que vai mal que traballe n’ela; hai sitio para todos. (Castelao)
Responder Con Cita
  #2  
Antiguo 29-01-2008
Avatar de duilioisola
[duilioisola] duilioisola is offline
Miembro Premium
 
Registrado: ago 2007
Ubicación: Barcelona, España
Posts: 1.734
Poder: 20
duilioisola Es un diamante en brutoduilioisola Es un diamante en brutoduilioisola Es un diamante en bruto
Esta parte del código es diferente entre FibPlus e IBX
Código Delphi [-]
      while seguir do
        try
          T.StartTransaction;
          Q.ExecQuery;
          T.Commit;
          Seguir := false;
+-------- DMDatos.Rollback;
|         AbrirTablas
|       except 
+----->     //Control de errores
        end;

En principio, si se genera la excepción no ejecutas el rollback.
Creo que deberías poner el Rollback en la parte del except.

También puede ser que tengas CacheUpdates = true.

Última edición por duilioisola fecha: 29-01-2008 a las 13:28:35.
Responder Con Cita
  #3  
Antiguo 29-01-2008
Avatar de Ivanzinho
[Ivanzinho] Ivanzinho is offline
Miembro Premium
 
Registrado: ene 2005
Ubicación: Galicia
Posts: 595
Poder: 20
Ivanzinho Va por buen camino
No es distinta la parte de código entre IBX y FIB, esta última rutina la creé para hacer la inserción desde otra transacción. El rollback que hago ahí es de la transacción que controla el DataSet de movimientos, para volver a abrir las tablas con los datos actualizado. El rollback que va en el except es el de la transacción T.

Muchas gracias por tu atención duilioisola.

Un saúdo
__________________
Si no lees esto no vivirás tranquilo
Non lle poñades chatas â obra namentras non se remata. O que pense que vai mal que traballe n’ela; hai sitio para todos. (Castelao)
Responder Con Cita
  #4  
Antiguo 29-01-2008
Avatar de duilioisola
[duilioisola] duilioisola is offline
Miembro Premium
 
Registrado: ago 2007
Ubicación: Barcelona, España
Posts: 1.734
Poder: 20
duilioisola Es un diamante en brutoduilioisola Es un diamante en brutoduilioisola Es un diamante en bruto
Vale,
Postea el código de AbrirTablas.

Si la inserción y el selct están en dos transacciones diferentes, nunca se verán.

Código:
{Abro transacciones}
  T1.StartTransaction
  T2.StartTransaction

{Hago una cosa en cada una}
  T2.Insertarcampos
  T1.Select  <------ Topdavía no se ha enterado de lo de T2

{Refresco la transaccion}
  T1.Commit
  T1.StartTransaction <------ Ahora sabe lo de T2

{Ahora ya veo lo que haya hecho T2}
  T1.Select

{Cierro transacciones}
  T1.Commit
  T2.Commit
Normalmente, cuando hago un procedimiento para abrir tablas, la filosofía es "Reabrir" tablas.
Si trabajas con mas de una transacción también deberás refrescarla.

Código Delphi [-]
  Tabla.Close;
  if (Tabla.Transaction.InTransaction) then
     Tabla.Transaction.Commit;
  Tabla.Transaction.StartTransaction;
  Tabla.Open;

Última edición por duilioisola fecha: 29-01-2008 a las 15:11:04.
Responder Con Cita
  #5  
Antiguo 29-01-2008
Avatar de Ivanzinho
[Ivanzinho] Ivanzinho is offline
Miembro Premium
 
Registrado: ene 2005
Ubicación: Galicia
Posts: 595
Poder: 20
Ivanzinho Va por buen camino
Hola duilioisola, gracias por tu atención, pero creo que no has entendido bien mi consulta, el último bloque de código, al que te refieres, es una simple prueba que hice para ver que pasaba si hacía la inserción en una transacción distinta.

Lo que hago en AbrirTablas es simplemente eso, reabrir los DataSet necesarios tras la finalización de una transacción. Y lo que hago en el último fragmento de código es lo siguiente.

Código:
{Abro las transacciones}
T.StarTransaction //DmDatos.IBTrFac ya está abierta

{Inserto los valores}
T.InsertarCampos //El select lo tengo realizado con anterioridad

{Finalizo transacciones}
T.Commit
dmDatos.IBTrFac.Rollback //No se realizó ningun cambio en esta transacción, hago Rollback para finalizarla, daría lo mismo hacer commit;

{Reabro los DataSet para ver los últimos registros insertados}
AbrirTablas
Pero repito, esto es sólo una prueba que realice con posterioridad, el problema con IBX está que si se borraron los datos de la tabla desde una transacción externa antes de insertar un registro tengo que terminar la transacción activa e iniciar una nueva, ya que sino me inserta un registro con id = ultimo id del data set + 1. Lo que me llama la atención es que la clave se calcula en un procedimiento almacenado en la base de datos.

¿Puede tener algo que ver con las propiedades de la transacción y que esté leyendo algo que fué modificado con anterioridad?, pero en caso hacer un insert desde otro lado, ahí si me actualiza bien la clave.

Lo tengo solucionado finalizando y volviendo a inciar la transacción antes del insert, pero lo que me extraña es que con insert si funciona bien, por lo que me gustaría saber a que era debido este comportamiento.

Un saúdo y gracias por la ayuda.
__________________
Si no lees esto no vivirás tranquilo
Non lle poñades chatas â obra namentras non se remata. O que pense que vai mal que traballe n’ela; hai sitio para todos. (Castelao)

Última edición por Ivanzinho fecha: 29-01-2008 a las 16:09:10.
Responder Con Cita
  #6  
Antiguo 29-01-2008
Avatar de Ivanzinho
[Ivanzinho] Ivanzinho is offline
Miembro Premium
 
Registrado: ene 2005
Ubicación: Galicia
Posts: 595
Poder: 20
Ivanzinho Va por buen camino
Cambié las propiedades de IBTransaction de SnapShot a Read Commited y así si lo hace bien , que alivio, ya se por qué era , en el caso del insert lo hacía bien, pero voy a explicar el por qué.

Cuando se hacía un insert tampoco tenía en cuenta las inserciones hechas desde otras transacciones, por lo que daba una violación de clave primaria, pero este error era tratado en el except y se resolvia de manera transparente, ya que se hacía un rollback (por lo tanto se iniciaba una nueva transacción) y se intentaba de nuevo la inserción, funcionando esta vez la inserción correctamente, puesto que la transacción estaba actualizada.

Entono el mea culpa y le devuelvo la reputación a IBX , el problema era que se me paso poner la transacción como Read Commited. Volveré a comprobar los resultados de las inserciones masivas, ya que de esta manera los resultados mejorarán para IBX.

Muchas gracias por vuestro interes, sobre todo a duilioisola. En caso de que quede alguna duda no duden en preguntar.

Un saúdo
__________________
Si no lees esto no vivirás tranquilo
Non lle poñades chatas â obra namentras non se remata. O que pense que vai mal que traballe n’ela; hai sitio para todos. (Castelao)
Responder Con Cita
  #7  
Antiguo 29-01-2008
Avatar de jachguate
jachguate jachguate is offline
Miembro
 
Registrado: may 2003
Ubicación: Guatemala
Posts: 6.254
Poder: 27
jachguate Va por buen camino
Cita:
Empezado por Ivanzinho Ver Mensaje
¿Puede tener algo que ver con las propiedades de la transacción y que esté leyendo algo que fué modificado con anterioridad?, pero en caso hacer un insert desde otro lado, ahí si me actualiza bien la clave.

Lo tengo solucionado finalizando y volviendo a inciar la transacción antes del insert, pero lo que me extraña es que con insert si funciona bien, por lo que me gustaría saber a que era debido este comportamiento.
Revisá la transacción, su modo de aislamiento debiera estar en ReadCommited y seguramente está en SnapShot, siendo el comportamiento que mencionas, el correcto para este nivel de aislamiento.

Hasta luego.



pd. ¿cuales fueron los resultados de tus mediciones?
__________________
Juan Antonio Castillo Hernández (jachguate)
Guía de Estilo | Etiqueta CODE | Búsca antes de preguntar | blog de jachguate
Responder Con Cita
  #8  
Antiguo 29-01-2008
Avatar de Ivanzinho
[Ivanzinho] Ivanzinho is offline
Miembro Premium
 
Registrado: ene 2005
Ubicación: Galicia
Posts: 595
Poder: 20
Ivanzinho Va por buen camino
Cita:
Empezado por jachguate Ver Mensaje
Revisá la transacción, su modo de aislamiento debiera estar en ReadCommited y seguramente está en SnapShot, siendo el comportamiento que mencionas, el correcto para este nivel de aislamiento.

Hasta luego.



pd. ¿cuales fueron los resultados de tus mediciones?
Se ve que las conexiones en le cielo/infierno van lentas , lo acabo de responder en mi post anterior, pero de todas maneras muchas gracias por la respuesta. Pena que no Hubiese un menor desfase horario, ya que me ahorrabas unos cuantos dolores de cabeza . Lo dicho, gracias

En cuanto a los resultados de las mediciones los volveré a realizar y cuando los tenga los posteo aquí.

Un saúdo.
__________________
Si no lees esto no vivirás tranquilo
Non lle poñades chatas â obra namentras non se remata. O que pense que vai mal que traballe n’ela; hai sitio para todos. (Castelao)
Responder Con Cita
  #9  
Antiguo 29-01-2008
cjmatador cjmatador is offline
Miembro
 
Registrado: ene 2008
Ubicación: La Paz Bolivia
Posts: 24
Poder: 0
cjmatador Va por buen camino
Smile nuevo

chicos soy nuevo aca bueno ni tan nuevo por que siempre veo los foros en los que muchas de mis dudas son esclarecidas ahora tengo una
como inicio un foro con un problemita que tengo?
les agradecere responder pronto

saludos

CJMATADOR
Responder Con Cita
  #10  
Antiguo 29-01-2008
Avatar de jachguate
jachguate jachguate is offline
Miembro
 
Registrado: may 2003
Ubicación: Guatemala
Posts: 6.254
Poder: 27
jachguate Va por buen camino
Cita:
Empezado por cjmatador Ver Mensaje
chicos soy nuevo aca
Bueno, pues bienvenido al ClubDelphi.

Cita:
Empezado por cjmatador Ver Mensaje
les agradecere responder pronto
En serio, creo que no has leído los foros lo suficiente, si no, seguro ya habrías leído la Guía de estilo

Cita:
Empezado por cjmatador Ver Mensaje
como inicio un foro con un problemita que tengo?
Para iniciar un nuevo hilo, ve al foro que corresponde de acuerdo al tema de tu pregunta, y buscá el botón "Nuevo Hilo", no sin antes leer la guía de estilo.

Hasta luego.

__________________
Juan Antonio Castillo Hernández (jachguate)
Guía de Estilo | Etiqueta CODE | Búsca antes de preguntar | blog de jachguate
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Funcionamiento del StoredProc carlosegs11 SQL 4 08-05-2007 19:39:16
funcionamiento del RSA gulder Varios 2 22-04-2007 00:43:45
...funcionamiento del gobierno.... Jure Humor 0 17-11-2004 22:43:34
Funcionamiento de BatchMove Tecnic2 Conexión con bases de datos 2 07-09-2004 10:34:39
Funcionamiento de un BDLookupComboBox TIKIMORE OOP 4 07-05-2003 16:13:49


La franja horaria es GMT +2. Ahora son las 20:26:22.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi