Conceptos básicos de SQL+RDBMS: ¿Qué es un Commit?

Posted by

Esta publicación es multiplataforma y es aplicable a todos los RDBMS.

Es interesante ver, como persona experta en una herramienta técnica, algunas de las desventajas de las nuevas formas de aprender temas técnicos. Cuando comencé en TI, se aprendían algunos de los conceptos en la universidad, otras cosas trabajando en la oficina con otros DBA que sabían lo que estaban haciendo, y a su vez llenábamos los vacíos yendo a clases de una semana de duración una vez al año para obtener un entrenamiento oficial detallado y práctico. Si tenías suerte, cometías tus errores en entornos no productivos antes de poder cometerlos en producción, pero incluso con eso, la mayoría de los DBA que conozco tarde o temprano cometieron algún gran error cada dos años durante al menos su primera década de trabajo. Aprendí mucho de los errores que otros cometieron y a su vez también aprendí mucho de mis propios errores.

El enfoque actual del aprendizaje parece estar mucho más centrado en descubrir qué se necesita de fuentes en internet: Youtube y Stack Overflow. Esto a veces significa que se aprende exactamente lo que se está buscando, pero es posible pasar por alto implicaciones mucho mayores.

No me malinterpreten, hoy yo misma aprendo de esta manera. No puedo imaginar los errores que estoy cometiendo y de los que ni siquiera me doy cuenta en Python y R, ya que los estoy aprendiendo por mi cuenta. No me estoy lamentando por los “buenos viejos tiempos” o abogando por volver a un modelo de formación obsoleto. Lo que me gustaría hacer es abordar algunas de las lagunas en mi campo de experiencia técnica cuando las vea. Espero que esto sea útil.

¿Qué es un Commit?

Tiendo a estar al acecho en foros relacionados con bases de datos y SQL en reddit, y un día alguien describió un problema que estaban viendo al usar DBeaver para acceder a una base de datos PostgreSQL. Describieron que a veces los resultados de CURRENT TIMESTAMP eran actuales y otras veces tenían hasta 30 minutos de retraso. Como DBA, sé que el TIMESTAMP ACTUAL permanece constante en una transacción, por lo que les pregunté sobre el commit. Respondieron con “Soy relativamente nuevo en sql, ¿qué quieres decir con commit?”. Como DBA, esta es una de las últimas cosas que deseas escuchar de un desarrollador, y sin embargo, diría que aproximadamente el 25% de los page outs (Cuando se escriben páginas de memoria a disco, dicho evento se denomina page-out. Por el contrario, cuando se leen páginas de disco y se cargan en memoria se denomina page-in. Nota del T.) de mi equipo el año pasado se debieron a transacciones de larga duración que los desarrolladores fallaron en consolidar (commit) o deshacer (rollback) .

Control de transacciones

Cuando se acceden o modifican datos en una base de datos relacional, a menudo se agrupan varias sentencias. El trabajo que usted le pide a la base de datos que haga no se externaliza hasta que usted emita explícita o implícitamente un COMMIT. Algunas herramientas que se utilizan para acceder a las bases de datos se encargan de esto mediante el uso de la confirmación automática (AUTOCOMMIT). El AUTOCOMMIT significa que todas y cada una de las sentencias que usted ejecuta en una base de datos se confirman inmediatamente después de ser ejecutadas. Es un comportamiento que se puede configurar en muchas herramientas, incluso en la línea de mandatos. Si usted no tiene muchos conocimientos de base de datos, esto es probablemente con lo que usted desearía comenzar. Sin embargo, algunos métodos de acceso, en particular las GUI, no utilizan este comportamiento de manera predeterminada. DBeaver parece ser uno de ellos. Si está utilizando SQL Magic con Python, siempre se confirma automáticamente y no se puede hacer de otra forma. Con DBeaver y otras herramientas, solo es cuestión de encontrar la casilla de verificación correcta en la configuración para habilitar la confirmación automática.

¿Por qué agrupar Sentencias en Transacciones?

Lo primero que hay que entender es por qué las bases de datos hacen esto así. Si ejecuto un mandato es porque quería que sucediera, ¿verdad?

La primera respuesta está en la A en ACID. Debido a que las bases de datos relacionales dividen la información sobre entidades relacionadas en diferentes tablas, a menudo una transacción lógica tiene que afectar a más de una tabla y, por lo tanto, consta de más de una sentencia. El ejemplo más simple de esto es una transacción bancaria. Digamos que una transacción simple consiste en sacar dinero de la cuenta de Paul y poner ese dinero en la cuenta de Melanie. Una transferencia. Cada una de esas acciones es una sentencia separada, pero si saco el dinero de la cuenta de Paul, y luego ocurre un fallo y el dinero nunca se coloca en la cuenta de Melanie, ¡eso no es aceptable para el banco, ni para Paul, ni para Melanie!

Para evitar ese tipo de fallo, agrupamos las dos sentencias (sacar dinero y poner dinero) en una transacción y nos aseguramos así de que si una de las acciones falla, ambas fallan. Este es un ejemplo simplificado, porque cada transacción del mundo real consta de docenas, cientos o incluso miles de sentencias.

Cuando usted se conecta a una base de datos y no utiliza la confirmación automática (autocommit), ese es el comienzo de una transacción. Cada acción que realicemos desde ese punto hasta la próxima instrucción COMMIT o ROLLBACK es parte de esa misma transacción. Cuando se desconecta, es probable que todo su trabajo quede consolidado o deshecho, en función de la herramienta que haya utilizado.

Niveles de Bloqueo y Aislamiento

Cuando usted ha ejecutado sentencias pero no ha emitido un COMMIT, otras conexiones pueden o no ver los cambios que ha realizado, dependiendo de su nivel de aislamiento. Un nivel de aislamiento controla si usted puede ver datos sucios (no consolidados) y también controla los tipos de bloqueos que usted adquiere en los datos cuando lo consulta o modifica.

Puede bloquear los datos incluso sólo visualizándolos, dependiendo de su herramienta de acceso y la configuración / niveles de aislamiento utilizados. Para obtener más información sobre los niveles de aislamiento, consulte Conceptos básicos de DB2: niveles de aislamiento y fenómenos de concurrencia. Si bien esa entrada de blog es específica de Db2, también incluye una tabla que muestra los nombres de nivel de aislamiento en varios RDBMS empresariales. Las diferentes plataformas difieren un poco en los niveles de aislamiento y en cómo se implementan, pero los conceptos y los fenómenos de concurrencia son universales.

La idea de bloquear datos sólo visualizándolos se asocia con mayor frecuencia con un nivel de aislamiento de lectura repetible (RR) o Serializable. Algunas herramientas de acceso a bases de datos establecen este nivel de aislamiento por defecto a menos que usted lo cambie.

¿Por qué desearía usted este comportamiento de la base de datos? Bueno, puede ocurrir que en algún código que usted escriba y que modifique datos, desee usted consultarlos primero y es posible que requiera que esos datos cambien entre el momento en que los consulta y el momento en que los cambia. Cuando entramos en el meollo del acceso concurrente a los mismos datos por miles de conexiones diferentes, se vuelve complicado.

La buena noticia aquí es que este es en gran medida un problema resuelto en RDBMS, y si está buscando acceso concurrente y la capacidad de cambiar los mismos datos, un sistema de administración de bases de datos relacionales generalmente lo hará mejor que cualquier otra metodología de almacenamiento de datos. Esta es también la “I” en ACID.

Rollback

Existe otra forma de utilizar este comportamiento de control de transacciones, pero debe tener cuidado.

Si tiene la confirmación automática desactivada (AUTOCOMMIT OFF), puede ejecutar una sentencia y luego, desde la misma conexión, consultar para ver cuáles son los resultados de esa declaración, antes de emitir el COMMIT.

Si no le gustan los resultados, puede emitir un comando ROLLBACK para deshacer todo el trabajo que ha realizado en esa transacción. Una vez que haya confirmado los cambios, no se pueden revertir sin funciones específicas de un RDBMS u otro.

La razón por la que debe tener cuidado es que ciertas acciones pueden desencadenar un COMMIT IMPLÍCITO, así que tenga cuidado si confía en esta forma de trabajar sin algo de práctica.

Externalización

El COMMIT tiene otro propósito principal. COMMIT es el punto en el que sus cambios de datos se escriben en el disco (= se externalizan). Algunas personas que trabajan con bases de datos no se dan cuenta, pero a diferencia de otras metodologías de almacenamiento en las que sólo puedo restaurar la última vez que se realizó una copia de seguridad, la mayoría de las bases de datos relacionales se pueden restaurar en cualquier microsegundo. Utilizan para ello diversas metodologías de registro (logging) y escritura en disco, y hay forma de configurarlas para que no se comporten de esta manera, pero esta es otra clara ventaja de los RDBMS sobre otros sistemas de almacenamiento.

Tamaño de transacción y registro

Tenga cuidado con lo que hace en una transacción. Debido al registro (logging), si hace demasiado en una transacción, puede llenar el espacio reservado para logging en la base de datos y hacer que ésta no esté disponible hasta que la transacción se deshaga. Uno de mis primeros errores de DBA fue emitir una gran eliminación que se ejecutó durante tres horas antes de que los registros de transacciones se consumieran por completo. Luego, la eliminación tuvo que revertirse antes de que cualquier actividad de actualización en la base de datos funcionara, que fueron otras dos horas. Esto fue para un sitio web de comercio electrónico y supuso una interrupción de dos horas para ese sitio. Las eliminaciones son particularmente problemáticas, pero las actualizaciones o las inserciones también pueden acarrear problemas similares. Compruebe siempre cuántas filas se verán afectadas antes de ejecutar una sentencia de eliminación o actualización para que no tenga usted que aprender esta lección de una forma dolorosa.

Comportamiento

¿Qué necesita usted hacer con esta información? Lo primero que le pediría, como DBA, es que comprenda si su aplicación o actividad puede tolerar datos sucios (no confirmados) y, si puede, configure su nivel de aislamiento correctamente. Lo segundo es hacer COMMIT con frecuencia, y NUNCA deje una transacción abierta cuando se aleje de su equipo. En la mayoría de los casos, la confirmación automática es su amiga, y debería habilitarla.

Términos y lecturas adicionales

El lenguaje en torno a la gestión de transacciones forma parte del estándar SQL y se denomina lenguaje de control de transacciones (TCL). TCL consiste principalmente en el comando COMMIT y varias formas del comando ROLLBACK. También es posible configurar SAVEPOINT para revertir hasta determinado punto de la transacción en caso de que haya múltiples escenarios de falla en la misma transacción.

Para Db2, la sección en la que con mayor frecuencia se falla en los exámenes de certificación es precisamente la sección sobre bloqueos, concurrencia y niveles de aislamiento. Esta es una de las cosas más importantes que debe comprender de su plataforma si está diseñando una aplicación en la que exista concurrencia de acceso a datos. Algunos enlaces por plataforma:

Db2 LUW
PostgreSQL
MySQL
MariaDB
MS SQL Server
Oracle

Avíseme en los comentarios a continuación si hay otros recursos que haya encontrado útiles al aprender sobre concurrencia, niveles de aislamiento, bloqueo y control de transacciones.

Leave a Reply

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.