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

借助由源私有文件系统支持的 SQLite Wasm,可以灵活地替代已弃用的 Web SQL 数据库技术。本文介绍了如何将数据从 Web SQL 迁移到 SQLite Wasm。

所需背景

弃用并移除 Web SQL 这篇博文宣布弃用 Web SQL 数据库技术。虽然该技术本身可能已弃用,但该技术所解决的用例并未弃用,因此后续博文由 Origin Private File System 支持的浏览器中的 SQLite Wasm 概述了一组替代技术,这些技术基于 SQLite 数据库、编译为 Web Assembly (Wasm),并由 origin private file system 提供支持。为了完成整个迁移过程,本文将介绍如何将数据库从 Web SQL 迁移到 SQLite Wasm。

迁移数据库

以下四个步骤演示了将 Web SQL 数据库迁移到 SQLite Wasm 的概念性思路,其中 SQLite 数据库由源专用文件系统提供支持。您可以根据自己的 Web SQL 迁移需求,在此基础上自定义代码。

要迁移的 Web SQL 数据库

本迁移指南的基本假设是,您有一个(或多个)现有的 Web SQL 数据库,其中包含与您的应用相关的数据。在下面的屏幕截图中,您可以看到一个名为 mydatabase 的示例数据库,其中包含一个将情绪映射到严重程度的 rainstorms 表。Chrome 开发者工具可让您查看 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 的所有详细信息,请参阅文章由 Origin Private File System 支持的浏览器中的 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 数据库文件,并对该数据库运行查询。如以下屏幕截图所示,rainstorm 表已正确导入到 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 数据库迁移到由源私有文件系统支持的 SQLite Wasm。他们不会注意到,自己的数据现在托管在 SQLite 数据库中的源专用文件系统中,而不再位于 Web SQL 中。总而言之,对于希望确保应用长期稳定性和可扩缩性的 Web 开发者来说,从 Web SQL 迁移到 SQLite 是必要的一步。虽然此过程可能需要一些前期投入,但更强大、更灵活且最重要的是能够应对未来变化的数据库解决方案带来的好处,让这些投入物有所值。