Usar transacciones en la base de datos

MySQL soporta nativamente las transacciones en las tablas InnoDB (y, por lo tanto, MariaDB y Percona).

Pero, ¿qué es eso de las transacciones?, vamos a verlo con un ejemplo muy simplificado.

En un sistema bancario, yo realizo una transferencia de 100 € a mi amigo Luis. Internamente, se hace un update de mi usuario restándome 100 € y se hace un nuevo update del usuario Luis añadiéndole 100 €. Hasta aquí todo correcto (y desde luego, muy simplificado).

Pero ¿qué pasa si después de quitarme a mí los 100 € el sistema falla y, por lo tanto, no le añade los 100 € a Luis?, pues que quedan 100 € perdidos en tierra de nadie.

Para evitar esto, están las transacciones. Tenemos una serie de operaciones, que se deben ejecutar todas, si todo va bien confirmamos y se ejecutan, si algo falla por el camino volvemos atrás y queda todo estaba.

Eso son las transacciones, que iniciamos con START TRANSACTION; o con BEGIN; y si todo es como esperábamos, la confirmamos (y se ejecuta) con COMMIT; o si detectamos algún fallo, volvemos atrás con ROLLBACK;

WordPress no está construido con transacciones, aunque nosotros podemos utilizarlas en nuestras consultas (en el 99 % de los casos no serían necesarias), pero nada nos impide utilizarlas en nuestras pruebas.

Escenario de uso real

En este caso, además de descargar la base de datos y realizarlo en local, era un poco complicado realizar el update y si iba mal, volver a restaurar la Base de Datos y volver a probar, así que usé las transacciones directamente en MySQL.

Se trataba de una web que llevaba online muchos años y había pasado por diversos hostings y de los miles de fotos que tenía, había unas 100 que no podía regenerar desde WP Cli por tener mal la ruta en los metadatos (wp media regenerate --only-missing).

Al ver uno de los errores Warning: Can't find "xxxyyyzzz" (ID 1881). y buscar el ID en la tabla wp_postmeta se veía que el valor de _wp_attached_file era incorrecto, del tipo /home/.xxxx/yyyy/www.zzzz.com/wp-content/uploads/2008/09/xxxyyyzzz.jpg en lugar de 2008/09/xxxyyyzzz.jpg

La solución era efectuar el reemplazo en la base de datos, pero para evitar errores y nuevas pruebas restaurando la base de datos, la solución fue comenzar una transacción, buscar, realizar update, buscar de nuevo, mirar el valor de ese campo ID en concreto y al comprobar que todo está correcto ejecutar el update.

START TRANSACTION;

SELECT * FROM wp_postmeta WHERE meta_value like '/home/.xxxx/yyyy/www.zzzz.com/wp-content/uploads/%';

UPDATE wp_postmeta SET meta_value = REPLACE(meta_value, '/home/.xxxx/yyyy/www.zzzz.com/wp-content/uploads/', '') WHERE meta_value like '/home/.xxxx/yyyy/www.zzzz.com/wp-content/uploads/%';

SELECT * FROM wp_postmeta WHERE meta_value like '/home/.xxxx/yyyy/www.zzzz.com/wp-content/uploads/%';

SELECT * FROM wp_postmeta WHERE post_id=1881;

ROLLBACK;

Iniciamos una transacción.

En la primera consulta buscamos todas las entradas que contengan dicha cadena y nos devuelve unos 100 registros.

En la segunda consulta ejecutamos un UPDATE eliminando esa cadena y manteniendo el resto de la ruta.

En la tercera consulta, volvemos a ejecutar la primera, pero ahora nos da cero resultados.

En la cuarta consulta miramos el postmeta del ID original para comprobar que la ruta está correcta.

Y a continuación volvemos todo al estado anterior.

MySQL transactions

Y todo ha quedado como estaba, sin ningún cambio, pero verificando que nuestra consulta era correcta. En realidad la manera correcta de utilizarlo es con comprobaciones y realizar ROLLBACK o COMMIT según el resultado.

Pero en este caso era algo manual, en el que reviso resultados y al ver que todo está correcto, simplemente ejecuto la consulta de UPDATE ya sin transacciones al comprobar que los resultados son los deseados.

Y como veis, esto mismo lo podemos aplicar a multitud de situaciones dónde no estamos seguros al 100 % de los resultados sobre la BD. Recordad siempre crear backups antes de hacer nada, por muy seguro que sea lo que vamos a hacer y si es posible, trabajad siempre sobre una copia (desarrollo, staging, local, etc.).

Date de alta en mi superlista ;)

No compartiré tus datos con nadie ni te bombardearé a correos, solo cuando publique una nueva entrada o cuando tenga algo interesante que compartir contigo.

Deja un comentario

Favicon Taberna WP
Resumen de privacidad

Esta web utiliza cookies para que podamos ofrecerte la mejor experiencia de usuario posible. La información de las cookies se almacena en tu navegador y realiza funciones tales como reconocerte cuando vuelves a nuestra web o ayudar a nuestro equipo a comprender qué secciones de la web encuentras más interesantes y útiles.