Continuando la práctica vista anteriormente, retomaremos el principio del manejo de bases de datos, pero utilizando las características ACID que habías comentado anteriormente. No te preocupes, que aquí las explicaremos en gran medida para comprender el término de “Transacción” que es el que estaremos utilizando más adelante para nuestras operaciones.
Solamente recuerda que para ésta práctica retomaremos lo mismo que ya teníamos de la práctica pasada (aplicación, base de datos, enlace DSN, etc.). Y con esta medida, trataremos de explicar cómo funcionan en cierta medida los sistemas de los Bancos (o cualquier lugar donde ocupen sistemas de bases de datos) para responder ante los fallos o errores que pudieran surgir durante el tratamiento de su información.
PostgreSQL Global Development Group (1996-2011) define a las transacciones como elementos clave sobre todos los sistemas de bases de datos, pudiendo efectuar con estos elementos varios pasos dentro de uno mismo, u operaciones de todo o nada (es decir, o se efectúa todo un bloque de operaciones o no se efectúa ninguno). Los estados intermedios entre estos pasos no son visibles a otras transacciones, y en caso de la ocurrencia de algún error se prevé que la transacción se cancele sobre todos los pasos que la componen.
Si te fijas, la definición de transacciones que da PostgreSQL ® implica ciertas características importantes de los sistemas de bases de datos. Éstas características se conocen como ACID:
- Atomicity (Atomicidad).- Se considera a cada transacción como una unidad de trabajo, o un bloque de operaciones, indicando con esto que o el trabajo se realiza en su totalidad (todo el bloque que comprende la transacción) o no se efectúa ninguna operación.
- Coherency (Coherencia).- La transacción mantiene la coherencia de los datos, es decir, que si los datos están en un momento (estado) correcto antes de la transacción, también lo deben estar después de ella.
- Isolating (Aislamiento).- Cada transacción se comporta como si fuera la única transacción dentro del sistema. Una transacción no tiene la posibilidad de ver las fases intermedias de otra transacción, hasta que terminan.
- Durability (Durabilidad o Permanencia).- Si una transacción se realiza de forma satisfactoria, el sistema garantiza que los datos se mantienen aunque el equipo falle (Microsoft, 2011).
Como puedes ver, el SMBD hace demasiadas cosas por nosotros, y precisamente, es el principio que trataremos de exponer aquí con nuestra aplicación en la base de datos, o se efectúa el bloque de operaciones que hayamos designado, o bien, no se efectúa ninguna, simulando que estamos comprando vía Internet, o directamente en el Banco, realizamos operaciones, y si hubo algún error en un momento determinado, regresaremos a un estado anterior de la transacción.
Para ello, retomaremos la información que nos proporciona PostgreSQL Global Development Group (1996-2011) en su sitio Web, para el manejo esencial de las transacciones en su SMBD. De entrada, algunos conceptos y comandos básicos:
- BEGIN;.- Comando que indica el inicio de una transacción.
- ROLLBACK;.- Retroceso a el estado anterior al inicio de la transacción.
- COMMIT;.- Cumplimiento del bloque de transacción y aseguramiento de la persistencia de los datos que contiene dicha transacción.
- SAVEPOINT nombrePunto;.- Generación de un punto intermedio de la transacción para regresar a dicho punto más que al inicio de la transacción.
Bueno, puede parecer confuso hasta este momento, pero hagamos un ejemplo sencillo, y luego se expondrá un video. Vamos siguiendo estos pasos:
BEGIN;
Select * from toperaciones;
Update toperaciones set ctienda=’ABCD’;
Select * from toperaciones;
ROLLBACK;
Select * from toperaciones;
COMMIT;
Parece extraño este código pero no lo es. Vamos explicándolo:
- Iniciamos el bloque de transacción con el comando “BEGIN;”
- Consultamos todos los registros de nuestra tabla “toperaciones” apareciendo en pantalla.
- Actualizamos TODOS los registros cambiando el nombre de la tienda (¡oh!, un error severo).
- Volvemos a consultar todos los registros y vemos que se ha hecho la actualización de los datos (técnicamente, el error).
- Efectuamos un “ROLLBACK;” para regresar nuestra base de datos a su estado anterior.
- Realizamos la consulta y vemos que todos nuestros datos persisten, es decir, se canceló la transacción regresando al punto inicial de la misma.
- Finalizamos la transacción con el comando “COMMIT;”.
Está interesante esta aplicación, pero podemos hacer más operaciones aún, utilizando los puntos de salvado (“savepoints”) para regresar a un punto determinado de la operación, y no solo al principio de la transacción:
BEGIN;
Select * from toperaciones;
Delete from toperaciones where ctienda=’Aurrera’;
Select * from toperaciones;
SAVEPOINT puntoguardado;
Delete from toperaciones;
Select * from toperaciones;
ROLLBACK TO puntoguardado;
Select * from toperaciones;
COMMIT;
La explicación de las operaciones:
- Iniciamos la transacción con el comando “BEGIN;”.
- Consultamos todos los registros de la tabla.
- Borramos todos los registros cuya tienda sea “Aurrera”, aclarando, esto no podremos recuperarlo posteriormente, pues está después del punto de guardado.
- Consultamos la tabla y vemos que se han borrado dichos registros.
- Generamos un punto de almacenamiento (al cual regresaremos) llamado “puntoguardado”.
- Borramos todos los registros.
- Consultamos que si se hayan borrado todos los registros (¡oh!, error nuevamente).
- Regresamos pero al punto guardado, no al inicio de la transacción, mediante el comando “ROLLBACK TO”.
- Consultamos y vemos que regresan todos los registros, excepto los que cuya tienda fuera “Aurrera”.
- Finalizamos la transacción con el comando “COMMIT;”.
Puede parecer un poco extraño este funcionamiento, pero en el siguiente video se da la explicación del uso de las transacciones utilizando la línea de comandos:
Video 1. Fundamento empírico de las transacciones en línea de comandos.
Con esto concluimos la explicación del primer punto, el uso de las transacciones dentro de nuestro SMBD. Ahora es momento de generar nuestra aplicación simulando las operaciones bancarias, donde tendrá las siguientes características de funcionamiento:
- Se retomará el código pasado de las altas de datos (ventas) y consultas de datos.
- Elegiremos cada qué número de operaciones se tendrá una consistencia de los datos (de 5 a 10 registros).
- En caso de algún error se regresará al estado anterior siempre y cuando no se haya cumplido el número de operaciones de almacenamiento definidas (por ejemplo, si elegimos bloques de 5 operaciones, y efectuamos 6, solo podremos retroceder 1 operación, permaneciendo las 5 operaciones previas).
Mucho ruido y pocas nueces, vamos a ver cómo quedaría nuestro programa en vista de diseño:
· Formulario: nombre “Form1”.
o Botones:
“btnEjecutaConsulta”, texto “Ejecuta consulta”.
“btnCancelaConsulta”, texto “Cancela consulta”.
“btnAltaDatos”, texto “Ingresa venta”.
“btnEstableceRetroceso”, texto “Establece retroceso”.
“btnErrorOperacion”, texto “Error en operación”.
o Cuadros de texto:
“txtCliente”, texto “1111222233334444”.
“txtCantidad”, texto “100.50”.
“txtTienda”, texto “Walmart”.
o Etiquetas:
“lblNumeroCliente”, texto “Cliente: “.
“lblCantidad”, texto “Cantidad: “.
“lblTienda”, texto “Tienda: “.
o Cuadros de opción:
“cmbEstableceRetroceso”, texto “5”, lista de datos: 5, 6, 7, 8, 9, 10.
o Visor de datos (DataGridView): dgrDatos.
Tu formulario debe tener la siguiente forma:
Figura 1. Formulario bajo nuevo diseño:
Todo perfecto, es momento de explicar su código, que con respecto al tema pasado si ha cambiado un poco, pero trataremos de explicarlo lo más coherente posible, empecemos con las variables globales (les llamo variables aunque técnicamente según Visual Studio ® deberían ser objetos, pero bueno):
Public conexion As OdbcConnection
Public comando As OdbcCommand
Public adaptador As OdbcDataAdapter
Public conjunto As DataSet
Public cantidadOperaciones As Integer
Public contador As Integer
Public puntosSalvados As Integer
Public puntoUltimo As String
Las primeras cuatro variables las habíamos explicado anteriormente, por ello no se repetirán. Donde entra en juego ahora la transacción es en las siguientes variables:
- cantidadOperaciones.- Variable que irá almacenando cuántas operaciones se irán almacenando, y cada que lleguemos al valor predeterminado, se reiniciará.
- contador.- Variable común para recorrer las operaciones que llevamos.
- puntosSalvados.- Variable que almacena los bloques de transacciones, por ejemplo, si establecidos el almacenamiento cada 5 operaciones, y llevamos 10 registros, esta variable tendrá un valor de 2, si llevamos 12, valdrá igual 2, si llevamos 15, valdrá 3, etc.
- puntoUltimo.- Variable de tipo texto que almacena el último punto de retorno almacenado por nuestra aplicación.
El código correspondiente al inicio de la aplicación (la carga del formulario principal), que cambiará un poco respecto a lo que manejamos anteriormente:
conexion = New OdbcConnection("dsn=odbcpostgres;uid=;pwd=;")
comando = New OdbcCommand
comando.Connection = conexion
adaptador = New OdbcDataAdapter
conjunto = New DataSet
conexion.Open()
MsgBox("Conexion establecida...", vbInformation)
dgrDatos.Enabled = False
btnEjecutaConsulta.Enabled = False
cmdCancelaConsulta.Enabled = False
cmdAltaDatos.Enabled = False
lblNumeroCliente.Enabled = False
txtCliente.Enabled = False
lblCantidad.Enabled = False
txtCantidad.Enabled = False
lblTienda.Enabled = False
txtTienda.Enabled = False
btnErrorOperacion.Enabled = False
puntosSalvados = 1
Nuevamente, existe código ya repetido del tema pasado (la conexión, la inicialización, etc.), lo único que cambia aquí es lo siguiente:
- Estamos “inhabilitando” diversos elementos de nuestro programa, específicamente aquellos que implican realizar operaciones, hasta que no se haga la elección del tamaño de transacciones de nuestro bloque.
- La variable “puntosSalvados” se inicializa con un valor de 1 (uno), puesto que estamos en el primer bloque de transacción.
El código que corresponde ahora es el del establecimiento de la cantidad de operaciones para nuestra transacción:
dgrDatos.Enabled = True
btnEjecutaConsulta.Enabled = True
cmdCancelaConsulta.Enabled = True
cmdAltaDatos.Enabled = True
lblNumeroCliente.Enabled = True
txtCliente.Enabled = True
lblCantidad.Enabled = True
txtCantidad.Enabled = True
lblTienda.Enabled = True
txtTienda.Enabled = True
btnErrorOperacion.Enabled = True
cantidadOperaciones = CInt(cmbEstableceRetroceso.Text)
contador = 1
btnEstableceRetroceso.Enabled = False
cmbEstableceRetroceso.Enabled = False
Nada del otro mundo, salvo los siguientes detalles:
- Todo lo que teníamos “inhabilitado” se habilitará en este momento, pues como ya elegimos la cantidad de operaciones a considerar para nuestra transacción, podemos ya efectuar dichas operaciones.
- Inhabilitamos todo lo que tenga que ver con la elección de operaciones para la transacción, pues ya definimos previamente el tamaño.
- La variable “cantidadOperaciones” almacenará el bloque de operaciones que hayamos elegido del cuadro de opciones previamente.
- Se inicializa “contador” con un valor de 1 (uno) pues estamos en la primer operación.
Tras haber definido el bloque de transacciones es momento de ver los códigos que ya teníamos anteriormente, el de efectuar la consulta:
comando.CommandText = "select * from toperaciones"
adaptador.SelectCommand = comando
conjunto.Clear()
adaptador.Fill(conjunto)
dgrDatos.DataSource = conjunto.Tables(0).DefaultView
Y el código de cancelar la consulta:
dgrDatos.DataSource = Nothing
No se dan más detalles sobre los mismos puesto que ya habían sido explicados en el tema pasado y sería un tanto redundante comentarlos nuevamente. Vamos con el primer código interesante, el de ingresar una venta, recordando que ciertas fracciones de código ya fueron dadas en el tema pasado:
Dim fechahora As Date
Dim fecha As String
Dim hora As String
If (txtCantidad.Text = "" Or txtCliente.Text = "" Or txtTienda.Text = "") Then
MsgBox("Error, dejaste algún parámetro sin contenido...", vbCritical)
Else
fecha = ""
hora = ""
fechahora = DateTime.Now
fecha = fechahora.Year & "/"
If fechahora.Month < 10 Then
fecha = fecha & "0" & fechahora.Month & "/"
Else
fecha = fecha & fechahora.Month & "/"
End If
If fechahora.Day < 10 Then
fecha = fecha & "0" & fechahora.Day
Else
fecha = fecha & fechahora.Day
End If
If fechahora.Hour < 10 Then
hora = hora & "0" & fechahora.Hour & ":"
Else
hora = hora & fechahora.Hour & ":"
End If
If fechahora.Minute < 10 Then
hora = hora & "0" & fechahora.Minute & ":"
Else
hora = hora & fechahora.Minute & ":"
End If
If fechahora.Second < 10 Then
hora = hora & "0" & fechahora.Second
Else
hora = hora & fechahora.Second
End If
If contador = 1 Then
comando.CommandText = "BEGIN;"
comando.ExecuteNonQuery()
comando.CommandText = "SAVEPOINT punto" & puntosSalvados & ";"
puntoUltimo = "punto" & puntosSalvados
comando.ExecuteNonQuery()
End If
comando.CommandText = "insert into toperaciones values ('" & fecha & "','" & hora & "','" & txtCliente.Text & "'," & txtCantidad.Text & ",'" & txtTienda.Text & "')"
comando.ExecuteNonQuery()
comando.CommandText = "select * from toperaciones"
adaptador.SelectCommand = comando
conjunto.Clear()
adaptador.Fill(conjunto)
dgrDatos.DataSource = conjunto.Tables(0).DefaultView
MsgBox("Venta realizada exitosamente...", vbInformation)
contador = contador + 1
If (contador > cantidadOperaciones) Then
puntosSalvados = puntosSalvados + 1
contador = 1
comando.CommandText = "COMMIT;"
comando.ExecuteNonQuery()
End If
End If
Las fracciones de código que nos competen en estos momentos se explicarán a continuación:
- Si el contador vale uno (1) entonces es señal de que deberemos efectuar el inicio de la transacción, mediante la ejecución del comando “BEGIN;”.
- Generamos el punto de almacenamiento, mediante el comando “SAVEPOINT”, pasando como parámetro extra el punto en el cual nos encontramos (como se explicó anteriormente).
- Almacenamos la posición del punto en la variable “puntoUltimo”.
- Efectuamos el alta de los datos, tal y como hicimos en el tema pasado (“insert into toperaciones values….”).
- Las siguientes sentencias implican que tan pronto vamos insertando los datos en la tabla “toperaciones” se va actualizando el “DataGridView” (que este código es igual al de las consultas, por eso no se especifica más de él).
- Se incrementa la variable “contador”, para ver cuántas operaciones llevamos.
- Si el contador es mayor que el número válido de operaciones que tenemos (cantidadOperaciones), incrementamos el número de “puntosSalvados” en uno (1), reiniciamos el “contador”, y terminamos el bloque de transacción con uso del comando “COMMIT;”.
- Esto puede parecer extraño pero recuerda que determinamos que cada “N” operaciones se iba a generar el guardado de las mismas, y no podríamos regresar al punto anterior a ellas dentro de nuestro programa.
La última fracción de código que nos interesa es la de ejecución del botón en caso de ocurrir algún problema con nuestras operaciones (efectuar un “ROLLBACK;”):
If contador <> 1 Then
comando.CommandText = "ROLLBACK TO " & puntoUltimo & ";"
comando.ExecuteNonQuery()
MsgBox("Operación regresada al estado anterior...", vbInformation)
comando.CommandText = "select * from toperaciones"
adaptador.SelectCommand = comando
conjunto.Clear()
adaptador.Fill(conjunto)
dgrDatos.DataSource = conjunto.Tables(0).DefaultView
contador = 1
End If
La explicación del código:
- Si el contador es distinto de uno (1), señal de que llevamos más de una operación.
- Efectuamos un “ROLLBACK;” al punto que nosotros hayamos definido mediante el uso de la variable “puntoUltimo”.
- Mostramos un mensaje indicando esta situación.
- Volvemos a consultar todos los datos para reflejar el cambio dentro del “DataGridView”.
- Si no llevamos ninguna operación de inicio del bloque de transacción, simplemente no podemos efectuar ninguno de estos comandos.
Listo, ya tenemos nuestra aplicación funcionando, pero, pues vamos a explicarla a detalle para ir demostrando su funcionamiento, de igual forma se ubicará un video explicando el funcionamiento de la aplicación. Empecemos con el inicio de la aplicación:
Vamos definir un bloque de transacción de 5 operaciones (es decir, cada 5 ventas se almacenará la información y no podremos regresar a un estado anterior):
Figura 3. Establecimiento del bloque de transacción.
Teniendo todo esto, ingresemos tres (3) ventas dentro de la tabla de operaciones:
Figura 4. Ventas ingresadas dentro de la tabla.
Generemos un error en la operación:
Figura 5. Mensaje informativo de retorno al punto anterior.
Vemos como dentro del “DataGridView” hemos regresado al punto anterior, señal de que hemos efectuado adecuadamente el “ROLLBACK;”. Vamos más allá, ingresemos siete (7) operaciones, cinco (5) operaciones con una tienda, y dos (2) operaciones con otra tienda:
Figura 6. Siete operaciones dentro de nuestra aplicación.
Hagamos la ejecución del error en la operación, y vemos cómo únicamente recuperamos las primeras cinco (5) operaciones, tal y como definimos dentro de nuestro bloque de transacciones:
Figura 7. Recuperación del bloque de transacción.
Si aún tras demostrar el funcionamiento de esta aplicación en este marco, tuvieras alguna duda, puedes observar el siguiente video, donde se demuestra, en tiempo real, el funcionamiento de esta aplicación que acabamos de generar:
Video 2. Sistema de transacciones en Visual Studio ®.
Con esto terminamos la utilización de las bases de datos, vinculadas con un lenguaje de programación, y mediante el uso de transacciones demostrando las propiedades ACID de los SMBD. Como se expresó, si algún motivo implica que el Banco, u otro servicio de cobranza, se ha hecho un cobro injusto, no le eches la culpa al SMBD, sino más bien a la aplicación que fue realizada (o a los hábiles vendedores que pasan dos veces tu tarjeta de crédito, ja, ja, ja).
Recuerda que se pueden armar cursos acorde a tus necesidades, tanto de sistemas computacionales, tecnologías educativas y educación en general, o bien, apoyo para tareas y desarrollo de proyectos conforme lo necesites. Actualmente ofrecemos los siguientes cursos ya disponibles y armados para su impartición conforme lo necesites:
- Programación en Java con Swing.
- Programación de sistemas Pocket PC.
- Programación de Sistemas Palm.
- Programación en lenguaje C (fundamentos de programación).
- Programación en PHP.
- Fundamentos de Bases de Datos.
De igual forma, la enseñanza es en línea, se resuelven dudas vía correo electrónico, chat, foros de discusión y distintos medios para que siempre estés comunicado y al pendiente de todo, y dispones del material completo vía Internet para su disposición cuando lo quieras, al momento que quieras y cuantas veces quieras. Para ello contamos con una plataforma de enseñanza en línea con varias herramientas para que estudies y aprendas de la mejor forma, a tu ritmo, conforme tus necesidades y enfatizando la comunicación en todo momento.
Pregunta por los cursos existentes o bien, si deseas, se te puede armar un curso acorde a tus necesidades de aprendizaje. Recordándote, tenemos (y podemos armar) cursos de los siguientes temas:
- Sistemas Computacionales.
- Control asistido por computadora.
- Paquetes informáticos.
- Lenguajes de programación.
- Bases de datos.
- Tecnologías educativas.
- Educación en general.
Referencias.
- Microsoft (2011). Propiedades ACID. Portal Web de MSDN Microsoft. Recuperado el 20 de Julio, 2011 de http://msdn.microsoft.com/es-es/library/aa719484%28v=vs.71%29.aspx
- PostgreSQL Global Development Group (1996-2011). 3.4. Transactions. Portal Web de PostgreSQL en su apartado de documentación técnica, capítulo 3, características avanzadas. Recuperado el 20 de Julio, 2011 de http://www.postgresql.org/docs/8.3/static/tutorial-transactions.html
Para descargar.
Si deseas descargar la información en formato de Microsoft ® Word para su posterior lectura, así como el código fuente de la aplicación, da click al enlace correspondiente: