10 puntos por GN⁺ 2024-01-16 | 1 comentarios | Compartir por WhatsApp

Activar/desactivar el modo Wal2

  • El modo "Wal2" de SQLite es muy similar al modo "wal (Write-Ahead Logging)".
  • Para cambiar la base de datos al modo wal2, usa el comando PRAGMA journal_mode = wal2;.
  • No es posible cambiar directamente del modo "wal" al modo "wal2"; primero hay que cambiar al modo rollback.
  • Para cambiar una base de datos en modo wal al modo wal2, usa PRAGMA journal_mode = delete; y luego PRAGMA journal_mode = wal2;.
  • Una base de datos en modo wal2 solo puede ser accedida por una versión de SQLite compilada con esa rama.
  • Si intentas usar otra versión de SQLite, se produce el error SQLITE_NOTADB.
  • Para cambiar una base de datos en modo wal2 al modo rollback y hacer que pueda ser accedida por todas las versiones de SQLite, usa el comando PRAGMA journal_mode = delete;.

Ventajas del modo Wal2

  • En el modo wal existente, cuando un escritor escribe datos en la base de datos, no modifica directamente el archivo de la base de datos, sino que agrega los datos nuevos al archivo "-wal".
  • Las operaciones de lectura leen datos tanto del archivo original de la base de datos como del archivo "-wal".
  • En algún momento, los datos del archivo "-wal" se copian al archivo de la base de datos; a esto se le llama "checkpoint".
  • El checkpoint puede realizarse explícitamente mediante PRAGMA wal_checkpoint o sqlite3_wal_checkpoint_v2(), o automáticamente configurando PRAGMA wal_autocheckpoint (configuración predeterminada).
  • El checkpointer no bloquea al escritor, y el escritor tampoco bloquea al checkpointer.
  • Sin embargo, si el escritor escribe en la base de datos durante un checkpoint, los datos nuevos se agregan al final del archivo wal, por lo que el archivo wal puede seguir creciendo.
  • En el modo wal2, no existe el problema de que el archivo wal crezca indefinidamente aunque el checkpointer no tenga oportunidad de completar su trabajo sin interrupciones.
  • El modo wal2 usa dos archivos wal en lugar de uno ("-wal" y "-wal2").
  • Cuando se escriben datos, el escritor comienza agregando los datos nuevos al primer archivo wal.
  • Cuando el primer archivo wal crece lo suficiente, el escritor comienza a agregar datos al segundo archivo wal.
  • Después, el primer archivo wal puede pasar por checkpoint y, cuando el segundo archivo wal crece lo suficiente y el primero ya fue checkpointed, se vuelve a cambiar al primero.

Programación de aplicaciones

  • Desde la perspectiva del usuario, la principal diferencia entre los modos wal y wal2 está relacionada con el checkpoint.
  • En el modo wal, se puede intentar hacer checkpoint en cualquier momento, pero en el modo wal2 solo es posible después de que el escritor haya cambiado al "otro" archivo wal.
  • En el modo wal, el wal-hook (callback) se invoca después de que se confirma una transacción usando como argumento el número total de páginas del archivo wal.
  • En el modo wal2, el wal-hook se invoca usando como argumento el total de páginas no checkpointed de los dos archivos wal, o con 0 como argumento si el "otro" archivo wal está vacío o ya fue checkpointed.
  • Se recomienda que los clientes usen para una base de datos en modo wal2 la misma estrategia de checkpoint que en el modo wal.
  • El wal-hook se invoca después de que la transacción se confirma en disco y se libera el bloqueo de la base de datos, pero ocurre dentro de la llamada a sqlite3_step().
  • En sistemas BEGIN CONCURRENT, en lugar de ejecutar el checkpoint dentro del wal-hook, se puede usar un hilo que posponga esta tarea hasta después de que se libere el mutex de la aplicación.

Opinión de GN⁺

  • El modo wal2 de SQLite ofrece una nueva forma de journaling que mejora la concurrencia y la eficiencia de la base de datos.
  • Resolver el problema del crecimiento infinito del archivo wal es importante para mejorar la estabilidad y el rendimiento del sistema.
  • Con la adopción del modo wal2, los desarrolladores necesitan replantear la estrategia de checkpoint de la base de datos e implementar una lógica de checkpoint adecuada para lograr una mejor concurrencia.

1 comentarios

 
GN⁺ 2024-01-16
Opiniones de Hacker News
  • En el modo WAL2 se usan dos archivos WAL en lugar de uno. Los archivos se nombran como "<base de datos>-wal" y "<base de datos>-wal2". Cuando se escriben datos en la base de datos, la operación de escritura comienza agregando nuevos datos al primer archivo WAL. Cuando el primer archivo WAL crece lo suficiente, las escrituras cambian a agregar datos al segundo archivo WAL. En ese punto, el primer archivo WAL puede hacer checkpoint (y luego sobrescribirse), y cuando el segundo archivo WAL crece lo suficiente y el primer archivo ya fue checkpointed, se vuelve a cambiar al primer archivo WAL. Este proceso continúa.

    • Este enfoque es muy lógico, así que no entiendo por qué el modo WAL no se implementó así desde el principio. Tal vez se consideró una optimización prematura.
    • Espero que este modo pase a estar disponible de forma general.
  • Bedrock

    • Bedrock es una rama más interesante.
    • Incluye las funciones WAL2 + CONCURRENT.
    • Es la rama que Expensify usa para escalar hasta 4M QPS en un solo nodo (hace 6 años).
  • Se comparte un enlace sobre la primitive left-right, una técnica similar al modo WAL2.

    • Esta técnica es anterior a la implementación enlazada, pero fue redescubierta de forma independiente, y en particular fue escrita para soportar otra base de datos SQL de alto rendimiento llamada Noria.
  • En el modo WAL2 se usan dos archivos WAL en lugar de uno. Los archivos se nombran como "<base de datos>-wal" y "<base de datos>-wal2".

    • Me pregunto cuánta gente borrará el archivo wal. Como cambiaron a wal2, podrían pensar que el archivo wal quedó sobrando.
  • Microsoft SQL Server usa una arquitectura similar, pero en lugar de archivos de log separados asigna Virtual Log Files (VLF) dentro del archivo de log físico (en disco). Los VLF se asignan en un ring buffer y puede haber miles de ellos.

  • Se nota que esta función todavía no ha sido lanzada.

  • Siempre me ha preocupado que WAL exista para ayudar a mantener la integridad de los datos y recuperarse de fallos. Pero el archivo en sí se escribe en lotes (y se confirma de forma confiable al disco) para ganar rendimiento, en vez de hacerlo después de cada cambio en la base de datos. ¿No contradice eso su propósito? En general, no específicamente sobre bases de datos, no he podido encontrar una respuesta sobre esto.

  • Me pregunto qué impacto tendrá esto en los nuevos sistemas distribuidos de SQLite como Litestream.

  • Entonces, ¿básicamente es double buffering para la base de datos? Tiene sentido.

  • El modo WAL2 fue incluido en los benchmarks de la investigación del backend HC-tree.