SQLite - 同一事务中的多个调用

SQLite - multiple calls in same transaction

感谢观看 - 我正在用 Typescript 编写前端 SPA。我正在使用 capacitorJS 来实现跨平台兼容性,并且我正在使用 @capacitor-community/sqlite 插件。 我是 SQLite 的新手,但不是一般的数据库。

在 SQL 站点上使用特定的 API 可能会使这变得复杂。
API 在这里:https://github.com/capacitor-community/sqlite#supported-methods

无论如何,API 不符合我的预期。

我想要一种能够启动事务、进行多次调用并最终提交事务(或在错误处理程序中回滚)的模式。如果我可以在同一个 txn 中进行读取调用,或者至少能够在写入 txn 打开时读取 outside txn,那就太好了。

默认情况下,这个 (capacitor-community/sqlite) 包装器正在围绕我进行的每个调用添加一个事务,除非我用 bool 参数覆盖。如果我覆盖,我负责将事务代码包含在 sql 语句块中。

我第一个天真的方法是发出一条语句来启动交易,然后它会进行额外的 api 调用,这些调用应该是 txn 的一部分,最后 运行 sql 声明 commit txn.
例如

async Transaction(actions: () => Promise<void>): Promise<void> {
    await SqliteService.Instance.db.execute('BEGIN TRANSACTION;', 
    try {
      await actions();
      await SqliteService.Instance.db.execute('COMMIT TRANSACTION;', false); //useTransaction = false
    } catch (e) {
      await SqliteService.Instance.db.execute('ROLLBACK TRANSACTION;', false); //useTransaction = false
      throw e;
    }

这根本不起作用。看起来这样的状态不会在通话之间保留。我认为有些事情(比如打开游标)会导致会话保持打开状态,但通常情况下,会话只会随着我对 API.
进行的每次调用而打开和关闭 我还没有尝试过用例如游标来保持事务打开,这似乎是一种反模式

当我仔细考虑时,似乎我可能必须在交易中发送一大块 SQL 才能让 SQLite 做我想做的事。

所以我正在考虑将我的 documentStore api 重写为,而不是直接调用 SQLite 到 运行 语句,而不是当我想在一个事务中做多件事时, 以提供 sqlBuilder 类型 class。然后我可以将多个语句粘合在一起。

...

但我喜欢当前的界面,重写我的 documentStore 上的 'write' 方法以具有某种 sqlBuilder 似乎是朝着不同方向迈出的一大步。 例如

async Transaction(sqlBuilder: (builder: WriteSqlBuilder<T>) => {statement: string, values: unknown[]} []) {
...

我想知道 - 人们通常如何在单个事务中的 SQLite 中执行多个操作(查询、写入)?

谢谢!

所以,这最终成为我使用的包装器中的一些特殊行为 capacitor-community/sqlite

拨打电话时executeSet({sql, params}[], transaction) 您可以传递一个布尔值来决定是否使用交易。这是一个帮手。 此 transaction 值默认为 true。当它设置为 true 时,包装库会自动为您在 sql 项目周围添加 BEGIN TRANSACTIONCOMMIT TRANSACTION(以及 ROLLBACK TRANSACTION,以防出现错误),所有这些都在一次调用中完成。

如果您显式地将 transaction 设置为 false,它将像普通的 SQLite 那样运行,为调用启动一个隐式事务,当调用完成时,这是最后一个 SQL语句,隐式事务被隐式提交。

让我感到困惑的是我在网络浏览器中进行开发工作(对于这个跨平台应用程序),所以我使用 jeep-sqlitejeep-sqlite 使用内存中的 sqlite 数据库,并有一个 saveToStore(dbName) 方法将 SQLite 字节刷新到 IndexedDb 条目中。

我认为发生的事情是我在交易过程中冲水了。刷新后,不再有活动交易。


最后,我在访问 SQLite 数据库包装器时使用 async-lock,并拥有自己的 async Transaction(actions: () => Promise<void>) 方法来处理 BEGIN/COMMIT/ROLLBACK 本身,以及一些通用的 DocumentStore 方法,这些方法进行隐式调用,然后包含在事务中。