【问题标题】:Replacing SQLite database while accessing it访问时替换 SQLite 数据库
【发布时间】:2011-04-04 08:53:11
【问题描述】:

我对 SQLite 完全陌生,我打算在 M2M / 客户端-服务器环境中使用它,在该环境中,数据库在服务器上生成,作为文件发送到客户端并在客户端上用于数据查找。

问题是:我可以在客户端同时使用它的同时替换整个数据库文件吗?

这个问题可能听起来很傻,但客户端是 Linux 瘦客户端,为了替换数据库文件,临时文件将被重命名为最终文件名。在 Linux 中,仍然打开旧版本文件的程序仍将访问旧数据,因为旧文件由操作系统保留,直到所有文件句柄都已关闭。只有新的 open()s 才能访问文件的新版本。

所以,简而言之:

  • 客户端随机访问 SQLite 数据库
  • 从服务器接收到新版本的数据库并写入临时文件
  • 临时文件重命名为 SQLite 数据库文件

我知道这是一个非常具体的问题,但也许有人可以告诉我这是否是 SQLite 的问题,或者是否有类似的方法可以在客户端运行时替换数据库。我确实想将一堆 SQL 语句从服务器发送到客户端来更新数据库。

【问题讨论】:

  • 三年后有什么智慧之言吗?我还对客户端具有只读访问权限的情况特别感兴趣。
  • 我监视数据库文件,当我注意到 inode 发生变化时,我关闭并重新打开数据库。工作正常。请注意,数据库不是很重(基于用户交互的一些查询)。

标签: sqlite client-server


【解决方案1】:

不,您不能只替换打开的 SQLite3 数据库文件。 SQLite 将继续使用相同的文件描述符(或 Windows 语言中的句柄),除非您关闭并重新打开数据库。更具体地说:

  • 删除和替换打开的文件要么没用 (Linux),要么不可能 (Windows)。 SQLite 永远不会看到新文件的内容。

  • 覆盖 SQLite3 数据库文件会导致数据损坏。来自SQLite3 documentation

    同样,如果一个恶意进程打开一个 数据库文件或日志并写入 将格式错误的数据放入其中, 那么数据库就会损坏。

    随意覆盖数据库文件的内容会导致一大堆问题:

    • 如果你很幸运,它只会导致数据库错误,无论如何都会迫使你重新打开数据库。
    • 根据您使用数据的方式,您的应用程序可能会崩溃和烧毁。
    • 您的应用程序可能会尝试在新文件上应用现有期刊。听起来很痛苦?是的!
    • 如果你真的很倒霉,用户只会从任何查询中得到无效的结果。

解决此问题的最佳方法是适当的客户端-服务器实现,其中客户端 DB 文件根据来自服务器的数据进行更新。从长远来看,这将带来更大的灵活性,同时还可以通过发送更新而不是整个文件来降低带宽需求。

如果不可能,您应该分三个离散步骤更新客户端数据库文件:

  • 向客户端应用程序发送消息以关闭数据库。这允许应用程序提交任何更改、删除任何日志文件并清理其内部状态。
  • 替换/覆盖文件。
  • 向客户端应用程序发送消息以重新打开数据库。不过,您必须重新设置所有准备好的语句。

如果您出于某种原因不想关闭数据库文件,那么您应该让您的应用程序(甚至是一个单独的进程)使用新文件作为输入来更新原始数据库文件。在这种情况下,您可能会对SQLite3 backup API 感兴趣。

【讨论】:

  • 感谢您的回复。你说Linux下没用。因此,当我 替换 数据库文件时,客户端仍在访问它并不会造成损害(即客户端仅对数据库文件使用单个文件描述符)。我的客户端不写入数据库(它是每日更新的查找数据表)并且经常自行重新启动或重新打开数据库。只要数据库仍然可用,客户在重新打开数据库之前仍然使用旧数据是没有问题的。据我了解,这应该可行。你同意吗?
  • @Udo G.:如果您的客户没有更新,则应该没有期刊混淆的危险。我尝试删除一个数据库文件,我的阅读器进程继续没有问题。 SQLite 出现 使用单个文件描述符 - 我不确定它是否总是 这样做。也就是说,我们正在谈论的是实现/特定于操作系统的行为,这种行为无论如何都没有记录在案,并且将来可能会发生变化。你真的想把你的代码建立在这样的一堆假设之上吗?
  • 有趣的是,这是错误的。如果您在使用 sqlite3 客户端访问文件时删除该文件,则会收到 i/o 错误。试试看。
猜你喜欢
  • 2010-09-22
  • 1970-01-01
  • 2012-04-04
  • 1970-01-01
  • 1970-01-01
  • 2017-08-04
  • 2011-07-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多