【问题标题】:Android sqlite backup/restore without overwritingAndroid sqlite 备份/恢复而不覆盖
【发布时间】:2016-02-05 15:04:26
【问题描述】:

简短形式的问题:从后续内容看来,我或许应该强调和简化我的问题的核心。核心是:Android 数据库的其他备份选项似乎存在恢复可能会覆盖数据库中当前数据的风险。是这样吗?有没有办法在没有这种风险的情况下进行备份/恢复?

.

长格式问题:查看了许多(相当多)有关在 Android 上备份 SQLite 数据库的问题后,我有一个问题找不到答案。

所有其他备份/恢复讨论都涉及将 db 文件保存到 SD(或 How to backup/restore SQLite database on Android to Dropbox 中的云),然后在需要时恢复它。我担心的是,恢复不会覆盖当前数据库吗?

我担心用户何时重新安装了他们使用了很短时间的应用(生成新数据),然后想要从应用的先前备份中导入数据。对于所有其他备份/恢复方法,恢复旧数据库文件似乎会覆盖当前数据库文件中的任何新数据。我想要的是一个备份选项,在恢复时,它会将备份中的数据添加到当前数据库中,以使其完整,而不会覆盖其中的任何其他内容。

其他方法会这样做吗?还是像我怀疑的那样,在这种情况下它们会覆盖?

如果他们确实覆盖了,那么我最好的备份选项可能是写出 csv 或 xml 文件或其他东西,我希望这些备份讨论是关于简单的方法来做到这一点。是否有任何流程可以加快该流程并使其变得容易,还是我必须手动完成所有这些操作?如果是这样,关于写入格式的建议以及为什么?

同样,有谁知道使用 BackupAgentHelper 的内置 Google 备份是否会出现同样的覆盖问题?

最后,如果我在任何时候最终都要进行数据迁移(类似于How to Restore SQLite Database from Backup after Core Data model has changed (lightweight migration)),我现在应该做什么(我仍处于数据库设计阶段)以使这种潜在的未来变化更容易看到- à-vis 这个备份过程?

【问题讨论】:

  • restore 你是说merge 吗? ...然后选项是或者我是否必须手动完成所有这些操作,因为它总是涉及某种应该应用的逻辑(fx:仅从备份中添加不存在的行,覆盖更新的行等.)
  • 我想是合并,但从备份合并。写入 XML 或其他文件要复杂得多,因此如果 DB 文件的复制在还原时进行合并会很好;我只是不确定我相信它会。
  • 合并不是恢复。合并来自备份没有区别。合并的细节取决于您的数据及其结构。
  • 在这种情况下,merge 可能不是我想要的,而 restore 是首先正确的选择。
  • @J. Natael,一些问题和 cmets 以更好地理解问题。 1-由于您担心旧备份数据会覆盖新数据,因此您似乎希望将备份数据“添加”到新数据中(不对新数据进行任何修改)。 2-根据您的应用程序创建数据(记录)的方式,在将旧记录“添加”到当前数据库时,您可能需要注意新记录的主键值与旧记录之间的任何冲突。只是指出;在您的情况下,这可能不是问题。 3- 涉及多少张表?

标签: android sqlite data-migration android-backup-service backup-strategies


【解决方案1】:

我认为在您描述的场景中,在不更改(或与之冲突)“新”数据的情况下恢复旧数据的问题并不难解决。似乎本质上您只想将旧数据(记录)“添加”到新数据库中,并假设旧数据与新数据没有逻辑冲突(也就是说,为旧数据)。我相信在恢复过程中处理主键冲突将是需要考虑的最重要的问题。

我们分两种情况:

1:您正在使用数据库的主键值自动生成功能(例如,使用 SQLite 表的 AUTOINCREMENT 列)。

假设“较新”的数据库记录在恢复过程开始之前可能使用了 1 到 10 的主键 (ROWID) 值。如果您有带有任何这些主键值(1 到 10)的“旧”数据库记录,那么只有在您想保留这些旧主键值时才会出现问题。为了避免这个问题,不要保留“旧”记录的“旧”主键值——在从“旧”数据库中读取记录后,只需保存“旧”记录的其他属性(列)的值并让数据库为这条“恢复”的记录生成一个新的主键值。本质上,“旧”记录与新的主键值一起保存。如果您担心在此“恢复”过程之后维护记录的时间顺序,我建议您还保留一个时间戳列,其值不会在此过程中更改。

2:您正在使用替代机制(UUID、序列生成器等)来生成主键值:

在这种情况下,读取“旧”记录并在将其保存到“较新”数据库之前,将“旧”主键值替换为使用备用机制生成的主键值——按照设计,这将保证'restored' 记录的主键值相对于预先存在的'newer' 记录的唯一性。

为了简化此“恢复”过程的编程工作,尤其是在处理多个表时,您可以使用像 JDXA 这样的 ORM。 SDK 附带的一个示例应用程序说明了在将数据库升级到较新版本时传输“旧”数据的类似技术。 JDXA 还提供了一种方便的序列生成器机制,可以轻松高效地创建唯一 ID,您可以在持久化对象之前将其分配给它们。

【讨论】:

  • 感谢您抽出宝贵时间跟进如此深入的内容!我认为这偏离了重点。如果我备份到 XML 或类似的东西,那么在恢复期间,您讨论的两种方法就会发挥作用;如果我必须从 XML 恢复它当然是可行的,只是更复杂。不过我的问题是,有没有更简单的方法来备份/恢复我的数据库?如果没有,那么我需要生成一堆代码来将我的数据库写入 XML 并从中读回。
  • 不客气。我描述的方法可用于将数据从预先存在的数据库(SQLite db 文件)恢复到新数据库(另一个 SQLite db 文件),而无需借助任何 XML。 JDXA ORM 可以简化这个过程。
  • 嗯,在那种情况下,我想我误解了你的答案,这是比我发现的任何其他方法更好的方法。我将此标记为答案。如果我研究 JDXA ORM,我是否会找到从预先存在的 SQLITE db 文件恢复所需的所有信息,或者我还应该研究什么?
  • 请查看 SDK 附带的示例应用程序 JDXAndroidDBUpgradeV1Example 和 JDXAndroidDBUpgradeV2Example,了解如何将数据从旧数据库传输到新数据库的示例。如果您需要更多信息或帮助,我们可以离线处理。
  • SDK附带的JDXA ORM用户手册,详细介绍了数据库版本升级过程中的数据迁移策略。您可以通过访问link 下载 SDK。
【解决方案2】:

经过不断的研究,我越来越得出结论,没有更好的方法来解决这个问题。对于简单的备份,您可以像许多其他线程讨论的那样简单地复制数据库文件,并且不解决恢复时的覆盖问题(并且显然还存在兼容性问题:https://stackoverflow.com/a/10842043/3108762)。要获得真正强大的备份,您只需将整个数据库写入 XML,然后再将其读回,并完成所有相关工作。

https://stackoverflow.com/a/34477622/3108762 中提到了我发现的唯一更好的替代方案,它指的是新的 Android 功能 Configuring Auto Backup for Apps,但仅适用于 Android 6.0 及更高版本。我将对此进行测试,但如果它不起作用,并且对于 Marshmallow 以下的任何内容,似乎将我的整个数据库写入 XML,然后再次将其读回是唯一真正强大的方法。 不完全是一个惊喜,但很高兴知道。

【讨论】:

  • 正如我在之前对该线程的回复中提到的,您无需求助于将数据库导出为 XML 并将 XML 导入数据库。您可以使用我上面概述的方法处理覆盖还原问题。即使你想使用 XML 来解决数据库兼容性问题,你也可以用我帖子中提到的想法来处理主键冲突问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多