 |
Club Builder Foro de C++Builder en español
|
| Ver tema anterior :: Ver tema siguiente |
| Autor |
Mensaje |
Kurroman Lt

Registrado: 07 Dic 2003Mensajes: 79
|
Publicado: Sab 13 Dic, 2003 3:00 am Asunto: Una duda acerca de transacciones |
|
|
Si tengo una transaccion con supongamos 3 sentencias SQL en un cliente y una bd en un servidor. El hacer esa transaccion (de manera correcta) me garantiza q se ejecutan las 3 seguidas? Es decir, que no se ejecute la de otro usuario en medio?.
Explico la situacion que tengo. Supongamos que el cliente inserta un articulo y este tiene un campo autoincrementado por un trigger. Acto seguido la aplicacion consulta ese campo para que el cliente sepa el identificador de ese articulo. ¿Se puede dar el caso de que justo antes de consultar ese campo, se ejecute otra insercion de articulo de otro cliente y por tanto el primero reciba el identificador equivocado?
No se si me entendeis, igual me estoy liando solo o se hace esto de otra forma. Aconsejadme a ver. Gracias. |
|
| Volver arriba |
|
 |
Cesar C. Salazar Gonzalez Master


Registrado: 01 Oct 2002Mensajes: 2155Ubicación: San Cristóbal de Las Casas, Chiapas
|
Publicado: Sab 13 Dic, 2003 8:10 am Asunto: |
|
|
Mira, puedes utilizar, una tabla temporal en cada una de las estaciones (obiamente, es tu misma aplicacion instalada en cada una de las estaciones, eso supongo), para realizar tu transaccion, y cuando esté lista, para ser grabada, grabala en la base de datos, si ya tienes, el modo de grabado, pues solo depende de cual de tus estaciones llegue primero(grabe), pues en ese momento, el campo de incremento que se encuentra en tu servidor (digamoslo asi), automaticamente, lo va a incrementar
Espero haberte ayudado... Saludos... _________________
 |
|
| Volver arriba |
|
 |
XyVy Master


Registrado: 25 Ago 2002Mensajes: 557Ubicación: Murcia (España)
|
Publicado: Sab 13 Dic, 2003 9:55 am Asunto: |
|
|
Lo primero de todo es hacer algunas aclaraciones, una transacción es una operación atomica, dentro de una transacción o digamoslo mejor en el contexto de una transacción, pueden realizarse muchas operaciones SQL, mientras la transacción no haya sido Commited algo así como comprometida, en principio ningun otro usuario verá el resultado de esa transacción, por supuesto, si hablamos de Interbase/Firebird hay que decir que tienes tres tipos de aislamiento, los cuales harán que la BD se comporte de una u otra manera.
Hay que decir también que un trigger se realiza en el contexto de una transacción.
Las Transacciones se debe intentar que duren lo menos posible, luego tan pronto como escribas alguna modificación a tu BD, es importante que hagas un Commit() o CommitRetaining(), en el caso del primero luego deberás hacer un StartTransaction().
Las transacciones, triggers y demás cosas de BD de datos, no están para que no las uses, sino para que las uses, sino no las darían la solución que comenta César no la veo muy conveniente, no te preocupes por tu BD, pues el SGBD intentará que tu BD nunca esté en un estado inconsistente.
Cuando varios usuarios escriben en un base de datos y los usuarios realizan un Commit(), tu no sabes cual usuario asegurará sus datos en la BD primero, pero si sabes que sus datos se ejectarán atomicamente, luego en principio no te tienes que preocupar de si se van intercalar escrituras de una u otra transacción, pues todas se harán en orden es decir primero una transacción, luego otra, luego otra, etc.
Consulta el isolation level de interbase/firebird, allí te explica los diferentes modos, de que los demás usuarios, puedan ver o no los cambios que se van haciendo por otros usuarios.
En el caso que expones, creo entender que hay varios usuarios accediendo concurrentemente a la BD, dices que imaginemos que un usuario realiza una insercción (se ejecutaría su trigger para asignarle un campo primario a la tupla insertada) entonces antes de volver a consultar la BD otro usuario realiza otra insercción, y preguntas si el primero lee ahora el la tupla que insertó leerá otro valor que no era el suyo, pues logicamente dependerá de como te posicionas en ese registro, desde luego si por ejemplo (de forma erronea) te posicionas con Last(), pues muy mal, porque logicamente lees el ultimo, pero quien te dice a tí, que el ultimo en ese momento, aunque lo hubieras escrito muy seguido, va a ser tu registro. Si quieres leerlo para saber que valor le ha asignado el trigger a tu tupla inicial, lo que debes hacer es una consulta que te devuelva esa tupla, comprendes ? Como solo te va a devolver (quizás un registro), pues en principio sería ese, podrías pensar que incluso te devolviera muchos registro luego tendriamos un pequeño problema, como realizas la insercción con una consulta o haciendo un Append() o Insert()?
Ciao. _________________ OJO!! Ya tenemos subforo de Bases de Datos!!
Gracias a los admins. |
|
| Volver arriba |
|
 |
Invitado
|
Publicado: Sab 13 Dic, 2003 2:30 pm Asunto: |
|
|
Gracias a los dos. La programacion d la aplicacion aun no la he empezado. Me gusta resolver dudas antes de comenzar. El caso es que yo normalmente programo en Java y sin usar ninguna herramienta tipo Borland Builder, de manera que no uso metodos como append(), post()... sino que programo "a pelo", asi q no puedo responderte aun XyVy. Las aplicaciones GUIs son algo tediosas de programar en Java y por eso estoy empezando con Builder c++, q al menos la sintaxis del código es algo parecida a Java.
Lo q queria saber creo q me lo has resuelto, que si hago un insert y luego un select en una transaccion, no se va a realizar enmedio ninguna operacion de otro usuario. |
|
| Volver arriba |
|
 |
Cesar C. Salazar Gonzalez Master


Registrado: 01 Oct 2002Mensajes: 2155Ubicación: San Cristóbal de Las Casas, Chiapas
|
Publicado: Sab 13 Dic, 2003 4:27 pm Asunto: |
|
|
Mira, lo que pense, es que estabas, realizando un punto de venta, y el problema de Integridad Referencial, que se dá, cuando, 2 estaciones venden al mismo tiempo, y en el servidor estan en la remision no.20
1.- cuando las dos venden a quien les das el numero 21?, recuerda que estan al mismo tiempo.
2.- si la estacion1, vende, primero y la estacion2 vende en segundo, es correcto, estacion1=21 y estacion2=22, pero que pasa si la estacion1, cancela la venta, la estacion2, no puede tener el numero 22, debe tener el numero 21, si lo asignas de inicio. pues pierdes una nota.. y eso es fraude...
fue por eso que envie el codigo para realizar la operacion, en una tabla local, y cuando estubieran seguros de grabar, esta se grabara en la manera correcta...
saludos.. _________________
 |
|
| Volver arriba |
|
 |
Kurroman Lt

Registrado: 07 Dic 2003Mensajes: 79
|
Publicado: Sab 13 Dic, 2003 6:19 pm Asunto: |
|
|
El caso real que tengo es el siguiente:
Una aplicacion en 8-10 ordenadores cliente y una servidor con Interbase 6. Los clientes realizan informes que se graban en la base de datos y cada informe debe llevar una referencia que deben saber al iniciar el proceso de creacion del informe.
Si consulto el ultimo informe y se lo muestro al cliente puede que haya otro cliente que también vea la misma referencia del informe. Cuando rellene los campos, el primero que termine el informe lo insertara con la referencia correcta pero el segundo no. Eso es lo que no tengo claro como solucionar. Es la primera aplicacion cliente/servidor que realizo que no sea web. |
|
| Volver arriba |
|
 |
XyVy Master


Registrado: 25 Ago 2002Mensajes: 557Ubicación: Murcia (España)
|
Publicado: Sab 13 Dic, 2003 7:04 pm Asunto: |
|
|
Primero comentar algo, lo que digo a continuación no es ningun tipo de pensamiento de enfado ni nada por el otro mundo , es simplemente un pensamiento que me ronda la cabeza, a raiz de leer tu comentario, pero no entiendo que problema plantea la Integridad Referencial, precisamente lo que intenta es evitar problemas y ayudar a programar menos por parte del desarrollador y más por parte del administrador, dejando esa parte de gestión dentro del SGBD lo que agiliza y da consitencia a los datos.
Sobre lo que comentas del nº de factura y si es fraude, es obvio que los números deben ser continuas, un generador no entiende de si hay huecos o no, así que eso es tarea del programador, o bien desarrollar procedimientos almacenados que nos garantizen eso. Es más no creo que la solución de usar tablas intermedias en los clientes garanticen eso, imagino que se traerá otro tipo de problemas con el mismo problema en cuestión, lo que está claro es que hará falta algo de programación ya sea dentro de los clientes o dentro de SGBD para garantizar esa continuidad en los números y que un generador no nos proporciona.
Un generador simplemente es un número que se almacena en el servidor y que se incrementa atomicamente para evitarnos números repetidos, pero no garantiza que no hayan huecos, pues es obvio que se puede hacer un rollback de la transacción.
Podriamos hacer un pequeño procedimiento almacenado y con una pequeña tabla en el servidor que nos de numeros intermedios no usados, pero esto ya es otro tema claro.
Lo que es obvio es que si un generador no sirve para ese caso en cuestión, donde además de ser clave primaria debe garantizar que los números sean continuos y números inexistentes entre medias, hay que desarrollar algo adicional que nos proporcione esta caracteristica. Realmente el generador no entiende de facturas, ni números continuos ni nada, lo unico que nos proporciona es un sistema de generar no números no repetidos muy útiles para utilizar como claves primarias, porque estas no se deben repetir deben ser únicas, y todos sabemos que hay veces que un objeto conceptual a representar en un tabla no nos proporciona unicidad, es entonces, cuando sabemos que es util un generador.
Sobre la solución desde luego seguro que unos optarán por unas y otros por otras, y quizás unas den ciertos problemas y otras soluciones den otros, pero no pensemos que los generadores ni las transacciones no sirven para nada (no digo que lo hayais pensado) sino que la gente no debe pensar que no funcionan bien al leer estos mensajes, pues tanto las transacciones como los generadores son utilisimos. Aunque quizás en este problema concreto no hayamos sabido usarlos convenientemente.
Está claro que la mejor manera de buscar soluciones más optimas es tomando varios puntos de vista. _________________ OJO!! Ya tenemos subforo de Bases de Datos!!
Gracias a los admins. |
|
| Volver arriba |
|
 |
Kurroman Lt

Registrado: 07 Dic 2003Mensajes: 79
|
Publicado: Sab 13 Dic, 2003 7:56 pm Asunto: |
|
|
yo es q no sabia que interbase no tenia campos autonumericos, asi que me ha pillado un poco verde el tema. Estoy por pasar de autonumericos y que la aplicacion genere las referencias concatenando un codigo de cada cliente, pero claro... no me convence la idea. O mostrar la referencia justo cuando se inserte el informe, lo que pasa que tendria que mostrarselo al final... yo k se  |
|
| Volver arriba |
|
 |
Invitado
|
Publicado: Sab 13 Dic, 2003 8:03 pm Asunto: |
|
|
| Cita: |
Mira, lo que pense, es que estabas, realizando un punto de venta, y el problema de Integridad Referencial, que se dá, cuando, 2 estaciones venden al mismo tiempo, y en el servidor estan en la remision no.20
1.- cuando las dos venden a quien les das el numero 21?, recuerda que estan al mismo tiempo.
|
A las dos. Si las dos estaciones empiezan su propia transacción, las dos por lo tanto obtienen el número 21 puesto que ninguna todavía ha guardado la factura y el último número es el 20.
| Cita: |
2.- si la estacion1, vende, primero y la estacion2 vende en segundo, es correcto, estacion1=21 y estacion2=22, pero que pasa si la estacion1, cancela la venta, la estacion2, no puede tener el numero 22, debe tener el numero 21, si lo asignas de inicio. pues pierdes una nota.. y eso es fraude...
|
Si la estación1 cancela la venta, no se produce el commit, no se comprometen los datos, no se guarda nada en la base de datos y por lo tanto el último número de factura sigue siendo 20.
El problema viene cuando la estación1 guarda la venta y se le asigna el número de factura 21. Cuando la estación2 intente guarda la venta, intentará guardar también la factura número 21 puesto que para la transacción en curso de la estación2 el último número de factura es el 20 aunque en la base de datos sea 21. Pero no pasa nada, puesto que el SGBD lanza una excepción porque hay una restricción de unicidad en la clave primaria de la tabla de facturas que indica que no se pueden repetir los números de factura. La excepción es recogida por la aplicación y procesada por su número de error SQL (creo que es el -803) Entonces caben dos opciones:
- Opcion 1: Se le pasa la pelota al usuario con el mensaje "no se puede guardar la factura porque ya existe el número de factura 21" El usuario corrige el error y pone 22 como el número de factura.
- Opción 2: Se vuelve a leer el último número de factura, pero en este caso fuera de la transacción actual, para obtener los últimos datos de la tabla. Obtenemos el número 21 y guardamos el 22.
Espero haber arrojado algo de luz sobre el tema, de todas formas, creo que lo mejor es que cada estación/usuario guarde la factura y el número de serie, algo que es totalmente legal y además ayuda al seguimiento de quien facturó una determinada factura. Por ejemplo, para la estación1, las numeraciones de facturas serían A1, A2, A3, ... y para la estación2, serían B1, B2, B3, ...
Un saludo. |
|
| Volver arriba |
|
 |
XyVy Master


Registrado: 25 Ago 2002Mensajes: 557Ubicación: Murcia (España)
|
Publicado: Sab 13 Dic, 2003 8:08 pm Asunto: |
|
|
Interbase no tiene autonúmericos como tal, pero un generador con su trigger es exactamente lo mismo y seguro que tiene exactamente los mismo problemas, que pueda tener un autonumerico, pues probablemente la implementación de ambos sea de la misma manera, no creo que ningun SGBD (no lo sé seguro) soporte autonúmericos que te asignes numeros intermedios disponibles, pues sería una operación a priori algo costosa, y en general se pretende que los SGBD tengan un rendimiento alto en cuanto a velocidad, es por eso que por ejemplo incluso en la versión 6 de Oracle y 3.53 de MySQL no había restricciones de integridad referencial, a costa de no dar estas opciones incrementaban la velocidad del gestor, o mejor dicho el no implementar la integridad referencial suponia no reduciar la velocidad de su gestor, pues esta implementacíon puede reducir el tiempo de respuesta del gestor.
Es algo así como los Indices, son utiles para realizar consultas rapidas, pero enlentecen las insercciones y modificaciones, luego hay que buscar el compromiso entre una cosa y la otra, y saber cuando es conveniente usar una cosa o no usarla.
Por eso comentaba en un post más arriba, que quizás o bien no hemos sabido dar una solución para el caso del nº de las facturas con autonumericos o bien ese caso no se presta al uso de los autonumericos o generadores.
Ciao y suerte. _________________ OJO!! Ya tenemos subforo de Bases de Datos!!
Gracias a los admins. |
|
| Volver arriba |
|
 |
Kurroman Lt

Registrado: 07 Dic 2003Mensajes: 79
|
Publicado: Sab 13 Dic, 2003 8:57 pm Asunto: |
|
|
jeje, al final nos hemos liado todos creo yo. Me parece buena idea aprovechar el lanzamiento de la excepcion SQL para solucionar el tema.
Muchisimas gracias a todos. |
|
| Volver arriba |
|
 |
XyVy Master


Registrado: 25 Ago 2002Mensajes: 557Ubicación: Murcia (España)
|
Publicado: Dom 14 Dic, 2003 10:42 am Asunto: |
|
|
Esas excepciones se lanzan cuando se intenta producir una inconsistencia en la BD, pues el SGBD Interbase/Firebird intenta evitarlas, de esa manera cuando se ejecuta alguna sentencia SQL que pueda provocar inconsistencia en la BD te tirá una excepción.
Por cierto buen apunte el del Invitado.
Ciao. _________________ OJO!! Ya tenemos subforo de Bases de Datos!!
Gracias a los admins. |
|
| Volver arriba |
|
 |
|
|
No puedes publicar temas nuevos en este foro No puedes responder a temas en este foro No puedes editar tus mensajes en este foro No puedes borrar tus mensajes en este foro No puedes votar en las encuestas de este foro
|
© 2002–2026 Club Builder · Funciona con phpBB.
|