0

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

.

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

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

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

其他方法会这样做吗?或者,正如我怀疑的那样,在这种情况下它们会覆盖吗?

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

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

最后,如果我最终要进行数据迁移(类似于如何在核心数据模型更改后从备份中恢复 SQLite 数据库(轻量级迁移)),我现在应该做什么(我仍处于数据库设计阶段) 使这种潜在的未来变化相对于这个备份过程更容易?

4

2 回答 2

0

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

让我们来看两个案例:

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

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

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

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

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

于 2016-02-10T23:39:49.947 回答
0

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

我发现的唯一更好的选择在https://stackoverflow.com/a/34477622/3108762中提到,它指的是新的 Android 功能为应用程序配置自动备份,但仅适用于 Android 6.0 及更高版本。我将对其进行测试,但如果它不起作用,并且对于 Marshmallow 以下的任何内容,似乎将我的整个数据库写入 XML,然后再次将其读回是唯一真正强大的方法。不完全是一个惊喜,但很高兴知道。

于 2016-02-11T14:27:30.643 回答