【问题标题】:SQlite transactions: change visibilitySQlite 事务:更改可见性
【发布时间】:2018-04-03 01:53:10
【问题描述】:

我知道事务应该强制执行 ACID 属性,但是 SQLite 中的 w.r.t 事务,a guy here 警告在同一连接上完成的事务对其他人可见:

默认情况下 — 在单个事务中完成的更改 SQLite 数据库连接对其他事务可见 立即连接 — 甚至在调用之前 SQLiteDatabase.endTransaction()

在 Medium 上,由于没有人指出,似乎是真实的建议。

现在,我正在阅读有关 enableWriteAheadLogging() 作为官方文档中并发 Db 访问的解决方案的信息,并发现:

此方法可以并行执行来自多个 同一数据库上的线程。它通过打开多个 连接到数据库并使用不同的数据库连接 对于每个查询。数据库日志模式也更改为启用 写入与读取同时进行。

如果未启用预写日志记录(默认),则不可能同时在数据库上进行读取和写入 时间。在修改数据库之前,writer 隐式获取一个 数据库上的排他锁,阻止读者访问 数据库,直到写入完成。

相比之下,当 启用预写日志记录(通过调用此方法),写入 操作发生在单独的日志文件中,允许继续读取 同时。在写入过程中,其他线程上的读者 将感知数据库的状态,就像它在写入之前一样 开始了。写入完成后,其他线程上的读取器将 感知数据库的新状态。

现在,如果您阅读上面突出显示的部分,您会看到默认情况下,在不启用预写日志记录的情况下,默认行为会阻止并发读/写访问并阻塞,直到当前操作完成。如果你将这与上面所说的进行对比,似乎有了事务,就没有这样的阻塞。

非事务性行为如何阻止您读取或写入 Db 而事务性行为会阻止您?

【问题讨论】:

    标签: android sqlite transactions


    【解决方案1】:

    默认情况下 — 在单个事务中完成的更改 SQLite 数据库连接对其他事务可见 立即连接 — 甚至在调用之前 SQLiteDatabase.endTransaction()

    您可能正在阅读(双关语)更多内容。即应用的更改将可用,即它们可以在连接中看到/读取它们尚未被写入/提交。

    只有当/如果

    • a) 外部AND ALL 内部/嵌套事务已被setTransactionSucccessful 标记为干净/OK AND

    • b) endTransaction 被调用

    更改已提交(写入磁盘)。即只有在 END 时/在 END 期间才会将数据写入磁盘。

    【讨论】:

      【解决方案2】:

      没有“非transactional behaviour”:

      除了在事务中之外,不能对数据库进行任何更改。任何更改数据库的命令(基本上是除 SELECT 之外的任何 SQL 命令)如果尚未生效,则将自动启动事务。自动启动的事务会在最后一个查询完成时提交。


      那家伙说的在技术上是错误的;没有“该连接上的其他交易”。 一个连接同时只能有一个活动事务。

      当多个线程共享同一个连接时,它们共享事务。 并且因为它们在同一个事务中,所以它们并不相互隔离。任何执行 BEGIN/COMMIT/ROLLBACK 或任何其他 SQL 语句的线程都会影响同一连接上的所有其他线程。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-14
      • 1970-01-01
      • 2013-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-12
      • 1970-01-01
      相关资源
      最近更新 更多