从 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 开发者工具,您可以查看用于调试的 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,但要点如下。请记住,此代码需要在工作器(库自动为您创建)中运行,并正确设置必需的 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 扩展程序将显示 Save File 对话框,以便您将文件保存到用户可见的文件系统中。保存数据库文件后,使用 SQLite 查看器应用浏览数据。Project Fugu API Showcase 包含多款可在浏览器中使用 SQLite 的应用。例如,借助 Sqlime - SQLite 园地,您可以从硬盘打开 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 是一个必要步骤。虽然此过程可能需要一些初始工作,但更可靠、更灵活,最重要的是,能够满足未来需求的数据库解决方案的优势,使其非常值得投资。