¿Cuándo usar transacciones?
#1
Escrito 08 octubre 2013 - 12:13
Resulta que tengo que hacer un desarrollo y estoy formando parte de un pequeño equipo. Bien, hasta aquí nada extraordinario. En una discusión de trabajo de esta mañana estábamos viendo algunas consultas a la BD (insert, update, delete, select y esas cosas), yo hablé un poco de las transacciones y de repente alguien del grupo me dice que "ellos no utilizan transacciones cuando se trata de hacer una consulta (el Select , se entiende), hubo ahí un entredicho respecto del tema y a mí me quedó la duda.
Sostienen que no hace falta una transacción en ese caso porque el select no modifica el estado de la BD. Yo contesté, que si bien no hay modificaciones, hay conexión, hay cálculos y hay una respuesta.
Mi duda es simple: ¿Una transacción debe usarse siempre que se vaya contra una BD, o en los select's no hace falta?
Yo sigo sosteniendo que siempre hay que usarlas, pero... me quedó la duda con esto.
Saludos.
Santiago.
#2
Escrito 08 octubre 2013 - 02:33
Solo iria en los SELECT en caso de utilizar tablas temporales.
"CREATE TEMPORARY TABLE miTabla...
SELECT FROM miTabla..."
Ahora como dices las transacciones llevan datos y calculos, sin embargo asi lleves una transacción y ocurra un Error de Servidor, ninguna transacción va a salvarte. Tendría en ese caso que existir un sistema oyente para vigilar que todas las transacciones concluyan. Ya hablamos de complejidad multiserver como un sistema bancarario o ERP.
Regresando al tema:
No, las transacciones en un SELECT simple de consulta no las considero necesarias, sin embargo en SELECT donde se plantea llenar una tabla siempre es una buena idea, por que puede que el dato leido tenga un error y siplemente provoque un fallo.
En ves de anular toda la operacion solo anula la ultima instrucción, dejando a uno la tarea de buscar y su caso replantear el query desde el punto donde ocurrio el error.
Uo digo que si los uses
#3
Escrito 08 octubre 2013 - 03:42
Mi duda es simple: ¿Una transacción debe usarse siempre que se vaya contra una BD, o en los select's no hace falta?
Yo sigo sosteniendo que siempre hay que usarlas, pero... me quedó la duda con esto.
Hola amigo, que buena pregunta has hecho.
Por definición una transacción protege una o varias operaciones de escritura en la base de datos cuya correcta aplicación debe ser asegurada para mantener coherencia en la base de datos. Sobre ello puedes leer más en la wikipedia http://en.wikipedia....se_transaction. Si nos atendemos a lo que establece la documentación oficial, una operación de lectura no necesita ser garantizada en una transacción pues en si misma no afecta la consistencia de la base de datos. Una sentencia de lectura al terminarse abrutamente por una caida del servidor o por una caida de la red no afectará la estructura de tus datos en el SGDB.
Pero OJO, es muy importante que sepas amigo mio que dependiendo el motor de base de datos que manejes, el usar transacciones en las lecturas puede incidir gravemente en el rendimiento del servidor de bases de datos por que al iniciar un bloque transaccional sobre una tabla esta será bloqueada por el servidor hasta la confirmación (commit) o cancelación (rollback) de la misma. Si estas usando bloques transaccionales en selects muy demandantes, estás provocando que las operaciones de escritura sean encoladas hasta la finalización del select y eso mi amigo puede provocar lentitud en tu servidor.
Saludos
#4
Escrito 08 octubre 2013 - 04:47
Hola amigo, que buena pregunta has hecho.
Por definición una transacción protege una o varias operaciones de escritura en la base de datos cuya correcta aplicación debe ser asegurada para mantener coerencia en la base de datos.
Solo por molestar!! debería decir: "coherencia" si fuese portugués estaría correcto.
#5
Escrito 08 octubre 2013 - 06:18
Pero si no hace falta usar una transacción en un select. ¿Cómo hago para NO usarla en, por ejemplo, IBX para Firebird? Sabemos que para llegar a la BD tengo que enganchar el IBQuery con un IBDatabase y un IBTransaction.
Saludos.
#6
Escrito 08 octubre 2013 - 11:45
Solo por molestar!! debería decir: "coherencia" si fuese portugués estaría correcto.
jejeje no amigo, ninguna molestia al contrario, gracias por la corrección. Un abrazo
#7
Escrito 08 octubre 2013 - 11:47
Muy bien, está claro hasta ahora.
Pero si no hace falta usar una transacción en un select. ¿Cómo hago para NO usarla en, por ejemplo, IBX para Firebird? Sabemos que para llegar a la BD tengo que enganchar el IBQuery con un IBDatabase y un IBTransaction.
Saludos.
Buen punto, desgraciadamente no soy experto en Firebird, por lo que tendremos que esperar que los expertos opinen. Saludos
#8
Escrito 09 octubre 2013 - 05:57
Hace un largo tiempo que no uso los componentes IBX, esa combinación ( IBQuery + IBDatabase + IBTransaction ) es necesaria no importa si el TIBQuery es usado solamente para lectura.
En el caso particular de Firebird (si no me equivoco Oracle también) el motor activa (o no sé si decir abre) una transacción para leer los registros ya sea vía Selects o una vista (View); esto es fácil de comprobar con IbExpert, quienes usan FibPlus, que al momento de realizar la consulta se activan los botones de Commit y Rollback.
Como indique no uso IBX, pero en el caso de FibPlus el componente de conexión tiene dos propiedades: ReadTransaction y WriteTransaction. El objetivo de estas propiedades es:
1.- Para ReadTransaction es la transacción que siempre estará activa/abierta, a lo largo del uso de la aplicación, para las lecturas a la BD.
2.- Para WriteTransaction es la transacción que se utiliza cuando se realiza escrituras en la BD (Insert, Update, Delete), que es la que menos tiempo esta activa/abierta.
3.- Al realizar un Commit/Rollback de la transacción el componente sabe que debe aplicar dicho proceso vía la WriteTransaction y así asegurar que los TDataSet abiertos y asociados no se cierren una vez terminado el proceso.
A mi entender, para el caso de Firebird (si no me equivoco Oracle también) el usar o no transacciones para lecturas no debe ser tema de discusión ya que el motor se encarga de activar/abrir la transacción. En MS SQL no creo factible bloquear los registros solo para leer.
#9
Escrito 09 octubre 2013 - 07:13
SELECT * FROM MIPROCEDIMIENTOSELECCIONABLE(PARAMETROS)
Además el que se ejecute un SQL select simple y no por vía "indirecta" como el ejemplo anterior no viola los principios ACID.
De forma indirecta TODO motor (al menos los SQL-support) ejecuta sus instrucciones. Lo que los marea a ustedes es que una cosa son las transacciones explícitas vs las implícitas.
Siento decirte amigo Poli que Firebird no es un motorcito que no utiliza, por defecto, a la vieja escuela los bloqueos explícitos como das a entender. Firebird, que proviene de Interbase fue el PRIMER motor que trajo a nivel práctico el concepto de mutiversión. Una técnica que no requiere estar bloqueando tablas ni campos, total o parcialmente. Técnica que se ha vuelto la estándar y terminando adoptando el resto de los motores.Hola amigo, que buena pregunta has hecho.
Por definición una transacción protege una o varias operaciones de escritura en la base de datos cuya correcta aplicación debe ser asegurada para mantener coherencia en la base de datos. Sobre ello puedes leer más en la wikipedia http://en.wikipedia....se_transaction. Si nos atendemos a lo que establece la documentación oficial, una operación de lectura no necesita ser garantizada en una transacción pues en si misma no afecta la consistencia de la base de datos. Una sentencia de lectura al terminarse abrutamente por una caida del servidor o por una caida de la red no afectará la estructura de tus datos en el SGDB.
Pero OJO, es muy importante que sepas amigo mio que dependiendo el motor de base de datos que manejes, el usar transacciones en las lecturas puede incidir gravemente en el rendimiento del servidor de bases de datos por que al iniciar un bloque transaccional sobre una tabla esta será bloqueada por el servidor hasta la confirmación (commit) o cancelación (rollback) de la misma. Si estas usando bloques transaccionales en selects muy demandantes, estás provocando que las operaciones de escritura sean encoladas hasta la finalización del select y eso mi amigo puede provocar lentitud en tu servidor.
Saludos
Se puede forzar a que efectúe el bloque explícito con una cláusula, aunque no es algo que se haga amenudo.
La otra arista del problema está en como es que se ha diseñado Interbase, desde su API, y en como se encaró en forma casi paralela el diseño de los componentes de acceso que cuenta IBX y otras suites similares. Existe el componente que abstrae el concepto de abstracción debido a que Interbase y Firebird dan validez a la transacción explícita y se tenga posibilidad de controlar el contexto de uso de ésta.
Saludos,
#10
Escrito 09 octubre 2013 - 07:24
Un ejemplo muy simple: Añades un registro, y antes del commit, usando esa misma transaccion, haces un select que te da, por ejemplo, la suma de un campo de la tabla... el registro nuevo aparece sumado. Si usas otra transaccion, el registro nuevo no aparece sumado, porque falta el commit.
Otro ejemplo más evidente: Cuando lanzas una copia de seguridad, está crea una transaccion de lectura, y si tarda 1 hora, todo lo que se commitee a la base de datos -que se puede seguir modificando libremente- no será visible para la transaccion de la copia, por lo que literalmente copias un "snapshoot" de los datos en el momento exacto en que lanzaste la copia.
No se bloquean registros en este proceso, por cierto, porque FB, como bien apunta delphius, usa "record versions" y no bloquea nada realmente, pero controla que una version modificada de un record no sobreescriba nunca otra version que no sea la que se empezó a editar (si alguien "se te adelanta" modificando los datos que leiste, no podrás guardar tus cambios).
En mis aplicaciones uso una transaccion por defecto de solo lectura para todos los select (grids) definido en el datamodule, y luego en cada ficha o proceso que modifique algo, uso una transaccion propia de la ficha de read-write.
Otra cosa es que los componentes que uses te lo escondan y esas cosas, pero sin transaccion, no hay query que enviarle a la base de datos. Y esto es así en FireBird, Oracle, SQL Server... todas las "serias". Pero no es así en las bases de datos que no sean "transaccionales" como ciertos motores de MySQL (por eso corre tanto), dbase (existen versiones transaccionales también pero son "rarezas"), ficheros CSV, XML, etc. (o las de Android, por ejemplo).
#11
Escrito 09 octubre 2013 - 07:46
Siento decirte amigo Poli que Firebird no es un motorcito que no utiliza, por defecto, a la vieja escuela los bloqueos explícitos como das a entender. Firebird, que proviene de Interbase fue el PRIMER motor que trajo a nivel práctico el concepto de mutiversión. Una técnica que no requiere estar bloqueando tablas ni campos, total o parcialmente. Técnica que se ha vuelto la estándar y terminando adoptando el resto de los motores.
Se puede forzar a que efectúe el bloque explícito con una cláusula, aunque no es algo que se haga amenudo.
Antes de comentar amigo, el compañero no había establecido que base de datos usaba por eso generalicé.
Sobre que firebird permitia bloqueos a nivel de registro o tabla antes que los demás, me parece un poco exagerado. La razón es que Tanto Db2 como Oracle implementan diferentes tipos de aislamiento desde hace mucho tiempo.
#12
Escrito 09 octubre 2013 - 07:56
Hubiera jurado leer que entre tus palabras estaba la palabra Firebird. Mis más sinceras disculpas amigo.
Siento decirte amigo Poli que Firebird no es un motorcito que no utiliza, por defecto, a la vieja escuela los bloqueos explícitos como das a entender. Firebird, que proviene de Interbase fue el PRIMER motor que trajo a nivel práctico el concepto de mutiversión. Una técnica que no requiere estar bloqueando tablas ni campos, total o parcialmente. Técnica que se ha vuelto la estándar y terminando adoptando el resto de los motores.
Se puede forzar a que efectúe el bloque explícito con una cláusula, aunque no es algo que se haga amenudo.
Antes de comentar amigo, el compañero no había establecido que base de datos usaba por eso generalicé.
Sobre que firebird permitia bloqueos a nivel de registro o tabla antes que los demás, me parece un poco exagerado. La razón es que Tanto Db2 como Oracle implementan diferentes tipos de aislamiento desde hace mucho tiempo.
Aunque téngase en cuenta, ya sea de paso, que Interbase fue el 1er motor que puso en práctica el nuevo paradigma de como proceder a llevar a cabo el manejo de transacciones y por supuesto de los puntos que conforman al concepto de ACID. Tal paradigma se conoce como snapshot o multiversión.
Modelo que efectivamente otros motores empezaron a imitar.
En términos prácticos y reales Interbase fue el primero en lograr ACID sin los bloqueos a nivel trabla y/o campos y poner en la mesa la palabra transacción.
Parte de la historia la podemos consultar en Wikipedia.
Saludos,
PD: Bueno... en realidad Interbase no fue el primero sino Digital's VAX Rdb/ELN pero este no llegó a nada. Y allí es donde entró Interbase.
#13
Escrito 09 octubre 2013 - 03:50
Cuando haces un Select sin iniciar una transacción, Firebird la inicia por ti con los parámetros por defecto: Read Write, Snapshot, Wait, que significa esto:
READ WRITE: Se abre una transacción para lectura y escritura. (Valor por defecto)
SNAPSHOT: Solamente se podrán obtener los datos que fueron “commiteados” antes de que la transacción empezara
WAIT: Si hay un conflicto con otra transacción porque ambas están queriendo actualizar o borrar la misma fila, esta transacción esperará hasta que la otra transacción termine.
Lo optimo es que tu inicies la transacción con Read Only(Se abre una transacción para lectura solamente), de esta manera obtendrás resultados más rápidamente.
Por esto es importante que uno mismo inicie las transacciones.
Saludos.
#14
Escrito 10 octubre 2013 - 04:13
http://conferences.e.../article/32280/