<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ANTONY PIERO SOLORZANO ZEGARRA</title>
    <description>The latest articles on DEV Community by ANTONY PIERO SOLORZANO ZEGARRA (@antonys3010).</description>
    <link>https://dev.to/antonys3010</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4160472%2F6fb1cdb8-88bb-4d5f-9c0c-98ac898765cc.png</url>
      <title>DEV Community: ANTONY PIERO SOLORZANO ZEGARRA</title>
      <link>https://dev.to/antonys3010</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/antonys3010"/>
    <language>en</language>
    <item>
      <title>Cómo saber si tu backup funciona: integridad y recuperación con SQLite — Adriana Laos</title>
      <dc:creator>ANTONY PIERO SOLORZANO ZEGARRA</dc:creator>
      <pubDate>Sat, 03 Oct 2026 21:01:40 +0000</pubDate>
      <link>https://dev.to/antonys3010/como-saber-si-tu-backup-funciona-integridad-y-recuperacion-con-sqlite-adriana-laos-55gp</link>
      <guid>https://dev.to/antonys3010/como-saber-si-tu-backup-funciona-integridad-y-recuperacion-con-sqlite-adriana-laos-55gp</guid>
      <description>&lt;p&gt;&lt;strong&gt;Artículo del equipo — integrante: Adriana Rafaela Laos Gonzales.&lt;/strong&gt; Publicado desde la cuenta del equipo administrada por Antony.&lt;/p&gt;

&lt;p&gt;Guardar un archivo y llamarlo «backup» no demuestra que los datos estén recuperables. Podemos conservar una copia incompleta, perder los cambios posteriores a ella o descubrir demasiado tarde que nadie conoce el procedimiento de restauración. En este artículo me centro en cómo comprobar la recuperación, usando un laboratorio con SQLite y registros ficticios.&lt;/p&gt;

&lt;h2&gt;
  
  
  El proyecto que vamos a comprobar
&lt;/h2&gt;

&lt;p&gt;El equipo construyó una pequeña aplicación de inventario. Usa SQLite en el navegador mediante sql.js y un laboratorio independiente en Python. No utiliza Microsoft SQL Server.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/AntonyS3010/sqlite-backup-lab" rel="noopener noreferrer"&gt;Código público&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://antonys3010.github.io/sqlite-backup-lab/" rel="noopener noreferrer"&gt;Aplicación desplegada&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/AntonyS3010/sqlite-backup-lab/actions" rel="noopener noreferrer"&gt;Automatización y pruebas&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La página funciona con datos de prueba y no requiere iniciar sesión. GitHub Pages publica la interfaz; la base se ejecuta en la memoria del navegador de cada visitante. Una recarga elimina el estado, de modo que no debe confundirse esta demostración con almacenamiento persistente en la nube.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tres preguntas distintas para una misma copia
&lt;/h2&gt;

&lt;p&gt;Antes de restaurar, conviene distinguir tres comprobaciones:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pregunta&lt;/th&gt;
&lt;th&gt;Comprobación del laboratorio&lt;/th&gt;
&lt;th&gt;Qué no garantiza&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;¿Cambió el archivo respecto del original?&lt;/td&gt;
&lt;td&gt;SHA-256&lt;/td&gt;
&lt;td&gt;No cifra ni autentica si un atacante puede reemplazar también el hash.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;¿La estructura de SQLite está íntegra?&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PRAGMA integrity_check&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No prueba por sí sola que los registros esperados estén presentes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;¿Recuperamos el contenido previsto?&lt;/td&gt;
&lt;td&gt;Comparar inventario ordenado por ID&lt;/td&gt;
&lt;td&gt;Solo valida los datos y reglas que realmente se comprobaron.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Son pruebas complementarias. Una base puede ser estructuralmente válida y estar vacía; también puede contener información desactualizada. Por eso la &lt;a href="https://www.sqlite.org/pragma.html#pragma_integrity_check" rel="noopener noreferrer"&gt;comprobación de integridad de SQLite&lt;/a&gt; forma parte del procedimiento, pero no es su único criterio de éxito.&lt;/p&gt;

&lt;h2&gt;
  
  
  Un experimento para entender el RPO
&lt;/h2&gt;

&lt;p&gt;El RPO expresa la pérdida de datos tolerable, normalmente en tiempo. La demo permite observar el efecto de guardar un estado anterior:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Abrir la aplicación: hay tres productos.&lt;/li&gt;
&lt;li&gt;Pulsar «Crear copia completa».&lt;/li&gt;
&lt;li&gt;Añadir un cuarto registro después de la copia.&lt;/li&gt;
&lt;li&gt;Pulsar «Simular pérdida de datos»; el inventario queda vacío.&lt;/li&gt;
&lt;li&gt;Restaurar y verificar.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;La recuperación devuelve los tres productos originales. El cuarto no vuelve porque fue creado después del backup. No es un error de restauración: la copia contiene un estado anterior. Esta diferencia permite entender por qué la frecuencia de backups debe responder a una necesidad concreta.&lt;/p&gt;

&lt;p&gt;Si una operación no tolera perder muchas transacciones, una copia completa ocasional puede ser insuficiente. Harían falta una frecuencia adecuada y, según el motor, otras estrategias de recuperación. Este proyecto no implementa backups incrementales, diferenciales ni recuperación a un instante específico.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recuperar de forma segura
&lt;/h2&gt;

&lt;p&gt;En la aplicación, primero se comprueba la copia y se construye una base candidata. Se verifica su integridad y se comparan sus registros con los guardados. Solo entonces se sustituye la base activa. Así, un fallo en la comprobación no reemplaza directamente los datos existentes.&lt;/p&gt;

&lt;p&gt;La API de sql.js permite obtener los bytes SQLite con &lt;code&gt;export()&lt;/code&gt; y crear una base con &lt;code&gt;new SQL.Database(bytes)&lt;/code&gt;, como indica su &lt;a href="https://sql.js.org/documentation/Database.html" rel="noopener noreferrer"&gt;documentación&lt;/a&gt;. Esta copia se conserva en memoria y puede descargarse como &lt;code&gt;.sqlite&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Para trabajar con una base SQLite activa fuera del navegador, no conviene copiar a ciegas el archivo principal. La &lt;a href="https://www.sqlite.org/backup.html" rel="noopener noreferrer"&gt;API oficial de backup de SQLite&lt;/a&gt; proporciona una forma de generar una copia consistente. En el laboratorio Python se usa &lt;code&gt;Connection.backup()&lt;/code&gt;. También se genera un dump con &lt;code&gt;iterdump()&lt;/code&gt; y se restaura en una base independiente, según la &lt;a href="https://docs.python.org/3/library/sqlite3.html" rel="noopener noreferrer"&gt;documentación de Python&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  El RTO va más allá del cronómetro
&lt;/h2&gt;

&lt;p&gt;La página muestra el tiempo local de restauración de una base mínima. Ese número sirve para observar la operación, pero no estima la recuperación de un sistema real.&lt;/p&gt;

&lt;p&gt;Un objetivo de RTO debe considerar localizar la copia, descargarla si está fuera del equipo, reconstruir el entorno, restaurar permisos y dependencias, ejecutar comprobaciones y confirmar que la aplicación vuelve a funcionar. Tres registros en memoria no representan una base grande ni una caída de infraestructura.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué automatizamos y qué debemos practicar
&lt;/h2&gt;

&lt;p&gt;El repositorio contiene un flujo de GitHub Actions que se ejecuta cuando cambia la rama &lt;code&gt;main&lt;/code&gt;. Primero prueba el ciclo de pérdida y recuperación en Python; si pasa, publica la aplicación en Pages. La configuración utiliza las &lt;a href="https://docs.github.com/en/pages/getting-started-with-github-pages/using-custom-workflows-with-github-pages" rel="noopener noreferrer"&gt;acciones de despliegue oficiales&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Esta automatización evita desplegar si falla la prueba incluida. No programa backups de una base de producción: las copias del navegador son manuales y el laboratorio usa datos generados para cada ejecución.&lt;/p&gt;

&lt;p&gt;Además de automatizar, mantendría un procedimiento breve de restauración: identificar la copia y su fecha, validar su referencia, recuperar en un entorno controlado, comprobar datos y registrar el resultado. Practicar ese procedimiento permite detectar problemas antes de una emergencia.&lt;/p&gt;

&lt;h2&gt;
  
  
  Guardar una copia donde el incidente no llegue
&lt;/h2&gt;

&lt;p&gt;La copia de esta demo está en el mismo dispositivo que la base. Si se pierde el equipo o se cierra la pestaña sin descargarla, también podemos perderla. Para un uso real propondría copias independientes, al menos una ubicación externa, retención definida, acceso restringido y cifrado. Una copia descargada en el mismo disco tampoco basta ante el fallo de ese disco.&lt;/p&gt;

&lt;p&gt;La estrategia debe evaluarse por su capacidad de recuperación. El ejercicio deja una evidencia concreta: podemos perder el inventario, reconstruir el estado guardado y comprobarlo, comprendiendo qué cambios quedan fuera.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Video del equipo:&lt;/strong&gt; añadir el enlace público después de publicarlo.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Texto preparado con asistencia de IA para el artículo correspondiente a esta integrante. Las pruebas del proyecto fueron ejecutadas localmente, en GitHub Actions y en la aplicación pública por el asistente del equipo.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>python</category>
      <category>testing</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Un backup sirve cuando puedes restaurarlo: laboratorio con SQLite y GitHub Actions</title>
      <dc:creator>ANTONY PIERO SOLORZANO ZEGARRA</dc:creator>
      <pubDate>Sat, 03 Oct 2026 20:29:26 +0000</pubDate>
      <link>https://dev.to/antonys3010/un-backup-sirve-cuando-puedes-restaurarlo-laboratorio-con-sqlite-y-github-actions-3i4p</link>
      <guid>https://dev.to/antonys3010/un-backup-sirve-cuando-puedes-restaurarlo-laboratorio-con-sqlite-y-github-actions-3i4p</guid>
      <description>&lt;p&gt;Una carpeta llena de copias no demuestra que una aplicación pueda recuperarse. Para comprobarlo, necesitamos provocar una pérdida controlada, restaurar una copia y verificar que los datos recuperados sean los esperados.&lt;/p&gt;

&lt;p&gt;Este proyecto usa SQLite y un inventario ficticio. No utiliza Microsoft SQL Server. Incluye una aplicación que ejecuta SQLite en el navegador y un laboratorio de Python que prueba copias físicas y lógicas.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/AntonyS3010/sqlite-backup-lab" rel="noopener noreferrer"&gt;Repositorio público y código&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://antonys3010.github.io/sqlite-backup-lab/" rel="noopener noreferrer"&gt;Aplicación pública: Backup Lab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AntonyS3010/sqlite-backup-lab/actions/runs/37151388887" rel="noopener noreferrer"&gt;Pruebas y despliegue con GitHub Actions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AntonyS3010/sqlite-backup-lab/blob/main/docs/video.md" rel="noopener noreferrer"&gt;Guion y tomas para el video de 4:30&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Primero, definir qué significa recuperarse
&lt;/h2&gt;

&lt;p&gt;El &lt;strong&gt;RPO&lt;/strong&gt; expresa cuántos cambios podemos permitirnos perder. Si guardo una copia y después ingreso una venta, restaurar esa copia no recuperará la venta posterior. El &lt;strong&gt;RTO&lt;/strong&gt; expresa cuánto tiempo podemos permitir que dure la recuperación; incluye localizar la copia, preparar el entorno y comprobar la aplicación.&lt;/p&gt;

&lt;p&gt;En esta demostración ambos conceptos se observan con pocos registros. El tiempo local mostrado es una medición del ejercicio, no una promesa para producción.&lt;/p&gt;

&lt;h2&gt;
  
  
  Elegir la estrategia
&lt;/h2&gt;

&lt;p&gt;Una copia completa conserva un estado íntegro y simplifica la recuperación, pero su coste aumenta con el volumen de datos. Una incremental guarda cambios desde la copia anterior y exige reconstruir la cadena; una diferencial guarda cambios desde la última completa. Este laboratorio implementa copias completas, no incrementales, diferenciales ni recuperación a un instante mediante logs.&lt;/p&gt;

&lt;p&gt;También hay formatos físicos y lógicos. En Python creo otra base SQLite mediante &lt;code&gt;Connection.backup()&lt;/code&gt; y genero un dump SQL con &lt;code&gt;iterdump()&lt;/code&gt;. El dump reconstruye esquema y registros, pero no conserva todos los detalles físicos del archivo. Ambas operaciones aparecen en la &lt;a href="https://docs.python.org/3/library/sqlite3.html" rel="noopener noreferrer"&gt;documentación de sqlite3 de Python&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Copiar un archivo activo sin coordinar escrituras puede producir una copia incorrecta o incompleta. SQLite ofrece su &lt;a href="https://www.sqlite.org/backup.html" rel="noopener noreferrer"&gt;Online Backup API&lt;/a&gt; y la alternativa &lt;a href="https://www.sqlite.org/lang_vacuum.html" rel="noopener noreferrer"&gt;&lt;code&gt;VACUUM INTO&lt;/code&gt;&lt;/a&gt;. Con WAL no debemos asumir que el archivo principal contiene todos los cambios confirmados. Aquí uso la API de backup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Construir el ejercicio reproducible
&lt;/h2&gt;

&lt;p&gt;El laboratorio funciona sin paquetes externos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 backup_demo.py &lt;span class="nt"&gt;--output&lt;/span&gt; lab-results
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El directorio debe ser nuevo para evitar sobrescrituras. El programa crea tres productos ficticios, obtiene una copia, calcula SHA-256 y genera un dump. Después vacía únicamente ese inventario desechable y restaura la copia.&lt;/p&gt;

&lt;p&gt;La operación central es:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;sqlite3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;live&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;backup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para recuperar invierto origen y destino. Antes de restaurar compruebo la copia y después comparo los registros con los originales. También reconstruyo otra base en memoria desde el dump SQL. El informe muestra filas iniciales, filas después del incidente, filas recuperadas e integridad.&lt;/p&gt;

&lt;p&gt;La prueba ejecutada obtuvo &lt;strong&gt;3 registros iniciales → 0 tras el incidente → 3 restaurados&lt;/strong&gt;, con &lt;code&gt;integrity_check&lt;/code&gt; correcto y restauración lógica correcta. GitHub Actions volvió a ejecutar la prueba antes de desplegar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Una demo que cualquiera puede probar
&lt;/h2&gt;

&lt;p&gt;La página usa sql.js para exportar bytes de una base SQLite y construir otra a partir de ellos, según la &lt;a href="https://sql.js.org/documentation/Database.html" rel="noopener noreferrer"&gt;documentación de Database&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Crear una copia de los tres productos.&lt;/li&gt;
&lt;li&gt;Añadir un cuarto registro después del backup.&lt;/li&gt;
&lt;li&gt;Simular la pérdida: el inventario queda vacío.&lt;/li&gt;
&lt;li&gt;Restaurar y comprobar que regresan los tres registros guardados.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;El cuarto registro no estaba en la copia y no vuelve: así observamos el RPO. La recuperación verifica SHA-256, integridad y contenido. Este recorrido se probó también en la aplicación pública.&lt;/p&gt;

&lt;p&gt;Podemos descargar la copia como &lt;code&gt;.sqlite&lt;/code&gt;. La base activa y la copia interna viven en memoria y se pierden al recargar. GitHub Pages aloja la interfaz pública; SQLite se ejecuta en el navegador de cada visitante. No hay un servidor de base de datos compartido ni un servicio de backups remotos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automatizar el despliegue
&lt;/h2&gt;

&lt;p&gt;El repositorio incluye &lt;code&gt;.github/workflows/pages.yml&lt;/code&gt;. Cada push a &lt;code&gt;main&lt;/code&gt; prueba la recuperación; solo si pasa, sube &lt;code&gt;site/&lt;/code&gt; y publica la aplicación en GitHub Pages. También puede iniciarse manualmente. Se habilita seleccionando GitHub Actions como origen de publicación en los ajustes del repositorio. El patrón está descrito en la &lt;a href="https://docs.github.com/en/pages/getting-started-with-github-pages/using-custom-workflows-with-github-pages" rel="noopener noreferrer"&gt;documentación oficial de Pages&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;El flujo no necesita contraseñas ni un token personal guardado en el código. Usa los permisos temporales de Actions. &lt;strong&gt;El despliegue es automático; el backup del navegador se crea al pulsar el botón.&lt;/strong&gt; Son procesos distintos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verificar y almacenar fuera del dispositivo
&lt;/h2&gt;

&lt;p&gt;SHA-256 detecta cambios si el hash de referencia es confiable; no cifra ni autentica la copia ante alguien que pueda sustituir archivo y hash. &lt;code&gt;PRAGMA integrity_check&lt;/code&gt; comprueba estructura, mientras que comparar registros valida el resultado concreto del ejercicio. Ninguno sustituye todas las comprobaciones funcionales de una aplicación real.&lt;/p&gt;

&lt;p&gt;Para un entorno real propondría tres copias, sistemas o medios de almacenamiento independientes y una ubicación externa, junto con permisos restringidos, cifrado y restauraciones periódicas. La copia del laboratorio en la misma memoria no cumple una estrategia 3-2-1.&lt;/p&gt;

&lt;p&gt;También definiría retención según el RPO: por ejemplo, diarias durante siete días y semanales durante cuatro semanas, ajustadas a la necesidad real. El proyecto no implementa esa retención.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lo que demuestra el proyecto
&lt;/h2&gt;

&lt;p&gt;La evidencia es recuperar el inventario y comprobarlo. Crear una copia es el inicio; localizarla, restaurarla y confiar en su contenido es el resultado que buscamos. El repositorio y la aplicación ya son públicos. El video todavía debe grabarse y publicarse; el guion está disponible en el enlace inicial.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Proyecto y redacción preparados con asistencia de IA; las pruebas de restauración se ejecutaron localmente, en GitHub Actions y en la demo web.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>githubactions</category>
      <category>python</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
