【问题标题】:Sync SQLite3 database with iCloud将 SQLite3 数据库与 iCloud 同步
【发布时间】:2016-06-30 13:22:43
【问题描述】:

这个问题已经被问过很多次了,但我一直找不到完整的答案。我需要使用 sqlite3 数据库将数据存储在我的应用程序中,并且核心数据不是一个选项。我想使用 iCloud 跨设备同步数据,最好的方法似乎是将 SQL 事务日志发送到 iCloud 并使用它们来保持设备最新。到目前为止我想出的过程如下:

  • 所有数据库更改查询(INSERT、UPDATE、DELETE)在执行后都存储在事务数组中,其中每个元素都包含 sql 查询及其执行的时间戳
  • 数据库包含一个表,用于记录应用程序最后到达的事务数组中的点(包括存储在 iCloud 上的事务文件的文件名)
  • 事务数组保存到 iCloud 上的设备唯一文件
  • 同步时:
    1. 从 iCloud 获取交易文件数组
    2. 创建要提交的事务的空数组
    3. 对于每个文件:
      • 检查数据库以获取事务文件中的最后一个位置
      • 如果没有,则从文件开头开始
      • 将每个事务从该点添加到要提交的事务数组中
      • 使用事务文件的新最后位置更新数据库,以免重复同步事务
    4. 按事务时间戳对要提交的事务数组进行排序
    5. 执行要提交的事务数组中的命令

我相信我可以通过将数据下拉到每个设备并执行命令来更新每个本地副本来完成这项工作。我设想的唯一问题是,如果两个设备在脱机然后同步时将记录插入同一个表。例如:

  1. 设备 1 和设备 2 都有同步的数据库副本,表“table1”中各有 4 条记录
  2. 设备 1 使用 PK 5 将值“foo”插入表“table1”
  3. 设备 2 使用 PK 5 将值“bar”插入表“table1”
  4. 设备 1 下载设备 2 的事务日志并将值“bar”插入 ID 6
  5. 设备 2 下载设备 1 的事务日志并将值“foo”插入 ID 6

我们现在遇到这样一种情况,即这些记录的主键在每台设备上都被反转,这将破坏到依赖主键进行链接的表的链接。

我仍在尝试研究解决此问题的方法,但与此同时,如果有人有任何建议,我将不胜感激!

【问题讨论】:

    标签: ios sqlite synchronization icloud


    【解决方案1】:

    我整天都在考虑这个问题,我想我已经想出了一个解决方案。我把它贴在这里看看是否有人有任何 cmets,我将在明天尝试实现它。

    我的想法是取消自动递增的整数主键,并将其替换为基于字符串的键。密钥将从设备的 UUID 和时间戳生成。这意味着密钥是特定于设备且行唯一的。因此,使用此方法改写上面的 INSERT 示例(使用简化的键字符串以便于阅读):

    1. 设备 1 和设备 2 都有数据库的同步副本,表“table1”中各有 4 条记录
    2. 设备 1 使用 PK“abc123”将值“foo”插入到表“table1”中
    3. 设备 2 使用 PK“def456”将值“bar”插入到表“table1”中
    4. 设备 1 下载设备 2 的事务日志并将值“bar”插入 ID“def456”
    5. 设备 2 下载设备 1 的事务日志并将值“foo”插入 ID“abc123”

    这是有效的,因为设备知道事务将导致插入使用设备特定值作为键的行。因此,插入操作后,keys 列中不存在重复值的危险。

    欢迎对这种方法提出任何想法!

    更新 我将其标记为正确答案,因为它有效。以下是我修改现有数据库(和应用程序)以允许跨设备同步的方式。幸运的是,这还不是一个生产应用程序,因此所需的数据库重大更改没有造成问题。

    1. 更改所有数据库表以使用 TEXT 类型的列作为它们的主键
    2. 向数据库中添加一个“最后一个索引”表,该表以表名作为键,并有另一列显示添加到该表的最后一行的索引号
    3. 向应用程序添加了一种方法,该方法通过检索表的最后插入索引并将其递增 1,然后将设备的 UUID 添加到该索引中来生成设备唯一和行唯一的 TEXT 键。
    4. 在插入任何行时,调用(3)中描述的方法来获取用于将记录插入数据库的适当键
    5. 所有数据库修改函数都会导致 SQL 查询被添加到事务日志中,每个条目也带有日期和时间戳,并使用设备的 UUID 作为文件名保存到本地文件中
    6. 然后将设备的本地事务日志推送到 iCloud
    7. 同步涉及以下内容:
      • 从 iCloud 下载所有交易日志
      • 忽略设备自己的事务日志,遍历每个日志中的 SQL 命令列表,并将它们添加到命令数组中,从上次同步时该日志完成的索引号开始
      • 将完成的索引号存储在数据库中,以便下次同步时不会重新执行相同的命令
      • 按日期对所有日志中所有 SQL 命令的数组进行排序
      • 按顺序执行命令

    关于这个过程的实现,我已经到了第 5 步。iCloud 特定的东西都还没有实现。但是,我已经通过在运行应用程序副本的设备之间手动复制事务日志来测试该过程,并且我可以确认该过程有效。包含设备 UUID 的 TEXT 主键确保不会发生冲突。所有设备都可以插入彼此的数据,并且密钥始终是唯一的。

    这样做的缺点是数据库会更大(因为键比整数长),并且查询可能需要更长的时间,因为涉及到大量的字符串比较。但是,我使用的数据库相对较小,每次用户交互只有几个查询,所以我预计这里不会出现问题。

    我希望这对其他提出相同问题的人有用:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-24
      • 1970-01-01
      • 2020-03-13
      • 2012-04-09
      • 1970-01-01
      • 2012-01-27
      相关资源
      最近更新 更多