从 Web SQL 到 SQLite Wasm:数据库迁移指南

借助由源私有文件系统支持的 SQLite Wasm,您可以使用通用方式替代已弃用的 Web SQL 数据库技术。本文将指导您将数据从 Web SQL 迁移到 SQLite Wasm。

必备背景

弃用并移除 Web SQL一文宣布了 Web SQL 数据库技术已被弃用。虽然该技术本身可能会被弃用,但该技术所解决的用例却不会被弃用,因此,后续文章《在由源私有文件系统支持的浏览器中使用 SQLite Wasm》概述了基于 SQLite 数据库、编译为 Web Assembly (Wasm) 且由源私有文件系统支持的一组替代技术。本文将介绍如何将数据库从 Web SQL 迁移到 SQLite Wasm。

迁移数据库

以下四个步骤演示了将 Web SQL 数据库迁移到 SQLite Wasm 的概念性想法,其中 SQLite 数据库由原始私有文件系统提供支持。这可以作为您根据自己的 Web SQL 迁移需求自定义的代码的基础。

要迁移的 Web SQL 数据库

本迁移指南的基本假设是,您有一个(或多个)现有的 Web SQL 数据库,其中包含与您的应用相关的数据。在下面的屏幕截图中,您会看到一个名为 mydatabase 的数据库示例,其中包含一个将情绪映射到严重程度的暴风雨表。借助 Chrome DevTools,您可以查看 Web SQL 数据库以进行调试,如下面的屏幕截图所示。

在 Chrome 开发者工具中检查的 Web SQL 数据库。该数据库名为 mydatabase,其中包含一个包含三列的表:行 ID、情绪和严重程度。示例数据有三行。

将 Web SQL 数据库转换为 SQL 语句

若要以对用户透明的方式迁移数据(即无需用户自行执行任何迁移步骤),则需要将数据库中的数据片段转换回最初创建这些数据的 SQL 语句。我们之前就遇到过这个问题,本文中使用的迁移脚本 mywebsqldump.js 基于名为 websqldump.js 的社区库,并进行了一些细微调整。以下代码示例展示了将 Web SQL 数据库 mydatabase 转换为一组 SQL 语句所需的代码。

websqldump.export({
  database: 'mydatabase',
  version: '1.0',
  success: function(sql) {
    // The SQL statements.
  },
  error: function(err) {
    // Handle the error.
  }
});

运行此代码会生成以下 SQL 语句字符串。

CREATE TABLE IF NOT EXISTS rainstorms (mood text, severity int);
INSERT INTO rainstorms(mood,severity) VALUES ('somber','6');
INSERT INTO rainstorms(mood,severity) VALUES ('rainy','8');
INSERT INTO rainstorms(mood,severity) VALUES ('stormy','2');

将数据导入 SQLite Wasm

接下来只需在 SQLite Wasm 上下文中执行这些 SQL 命令即可。如需详细了解如何设置 SQLite Wasm,请参阅由源私有文件系统支持的浏览器中的 SQLite Wasm一文,但下面再次简要介绍了相关要点。请注意,此代码需要在 Worker(由库自动为您创建)中运行,并正确设置必需的 HTTP 标头。您可以通过 npm 安装 @sqlite.org/sqlite-wasm 软件包。

import { sqlite3Worker1Promiser } from '@sqlite.org/sqlite-wasm';

(async () => {
  try {
    const promiser = await new Promise((resolve) => {
      const _promiser = sqlite3Worker1Promiser({
        onready: () => {
          resolve(_promiser);
        },
      });
    });

    let response;

    response = await promiser('open', {
      filename: 'file:mydatabase.db?vfs=opfs',
    });
    const { dbId } = response;

    const sql = `
      CREATE TABLE IF NOT EXISTS rainstorms (mood text, severity int);
      INSERT INTO rainstorms(mood,severity) VALUES ('somber','6');
      INSERT INTO rainstorms(mood,severity) VALUES ('rainy','8');
      INSERT INTO rainstorms(mood,severity) VALUES ('stormy','2');`
    await promiser('exec', { dbId, sql });

    await promiser('close', { dbId });
  } catch (err) {
    if (!(err instanceof Error)) {
      err = new Error(err.result.message);
    }
    console.error(err.name, err.message);
  }
})();

运行此代码后,使用 OPFS Explorer Chrome 开发者工具扩展程序检查导入的数据库文件。现在有两个文件,一个包含实际数据库,另一个包含日志记录信息。请注意,这两个文件位于源私有文件系统中,因此您需要使用 OPFS Explorer 扩展程序才能查看它们。

使用 OPFS Explorer Chrome 开发者工具检查源私有文件系统。有两个文件,一个名为 mydatabase.db,另一个名为 mydatabase.db-journal。

如需实际验证导入的数据是否与初始 Web SQL 数据相同,请点击文件 mydatabase.db,然后 OPFS Explorer 扩展程序会显示一个保存文件对话框,让您可以将文件保存到用户可见的文件系统中。保存数据库文件后,使用 SQLite 查看器应用探索数据。Project Fugu API Showcase 中提供了多个在浏览器中使用 SQLite 的应用。例如,借助 Sqlime - SQLite Playground,您可以从硬盘打开 SQLite 数据库文件,并对数据库运行查询。如以下屏幕截图所示,暴雨表已正确导入 SQLite。

在 Sqlime SQLite Playground 工具中探索 mydatabase.db 文件。该应用显示正在运行 SQL 查询 select star from rainstorms limit 10,从 Web SQL 的初始示例数据中返回了三行。

释放 Web SQL 存储空间

虽然无法删除 Web SQL 数据库(或许令人惊讶),但您仍然可以在将数据迁移到 SQLite Wasm 后,通过删除现已过时的 Web SQL 表来释放一些存储空间。如需列出 Web SQL 数据库中的所有表并使用 JavaScript 将其删除,请使用以下代码段中的代码:

const dropAllTables = () => {
  try {
    db.transaction(function (tx) {
      tx.executeSql(
        "SELECT name FROM sqlite_master WHERE type='table' AND name !='__WebKitDatabaseInfoTable__'",
        [],
        function (tx, result) {
          const len = result.rows.length;
          const tableNames = [];
          for (let i = 0; i < len; i++) {
            const tableName = result.rows.item(i).name;
            tableNames.push(`'${tableName}'`);
            db.transaction(function (tx) {
              tx.executeSql('DROP TABLE ' + tableName);
            });
          }
          console.log(`Dropped table${tableNames.length > 1 ? 's' : ''}: ${tableNames.join(', ')}.`);
        }
      );
    });
  } catch (err) {
    console.error(err.name, err.message);
  }
};

迁移后处理数据

迁移数据后,请按照此入门代码示例中所述的方式处理数据。如需了解详情,请参阅 SQLite Wasm API 参考文档。再次提醒一下,如果您使用原始私有文件系统作为存储后端,则需要从 Worker 访问 SQLite Wasm。

开始测试

通过此演示,您可以使用示例数据填充 Web SQL 数据库,然后将 Web SQL 数据转储为 SQL 语句,这些语句接下来会导入到由原始私有文件系统支持的 SQLite Wasm 中。最后,您可以通过删除过时的 Web SQL 数据来释放存储空间。如需查看完整实现(包括已修补的 mywebsqldump.js 文件),请参阅源代码

web-sql-to-sqlite-wasm.glitch.me 上的演示版应用。

总结

您可以采用对用户透明的方式,将 Web SQL 数据库迁移到由源专用文件系统支持的 SQLite Wasm。他们不会注意到,他们的数据现在托管在 SQLite 数据库中的原始私有文件系统中,不再位于 Web SQL 中。总体而言,对于希望确保应用长期稳定性和可扩缩性的 Web 开发者来说,从 Web SQL 迁移到 SQLite 是一项必不可少的步骤。虽然该过程可能需要一些初始工作,但更强大、更灵活且最重要的是具有前瞻性的数据库解决方案带来的好处,使得这项投资非常值得。