将SQLite3数据库与iCloud同步

时间:2016-03-15 08:07:35

标签: ios sqlite synchronization icloud

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

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

我相信我能够将数据提取到每个设备并执行更新每个本地副本的命令。我设想的唯一问题是两个设备是否在同一个表中插入记录,同时脱机然后同步。例如:

  1. 设备1和设备2都具有数据库的同步副本,表中各有四个记录" table1"
  2. 设备1插入值" foo"到表" table1"与PK 5
  3. 设备2插入值" bar"到表" table1"与PK 5
  4. 设备1下载设备2的事务日志并插入值" bar"至ID 6
  5. 设备2下载设备1的事务日志并插入值" foo"至ID 6
  6. 我们现在遇到这样一种情况,即每个设备上的这些记录的主键都被反转,这将破坏依赖主键进行链接的表的链接。

    我仍在尝试研究解决方案,但与此同时,如果有人提出建议,我将非常感激!

1 个答案:

答案 0 :(得分:0)

我一整天都在考虑这个问题,我想我已经找到了解决方案。我在这里发帖,看看是否有人有任何意见,我明天就会去实施。

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

  1. 设备1和设备2都具有数据库的同步副本,表中各有四个记录" table1"
  2. 设备1插入值" foo"到表" table1"与PK" abc123"
  3. 设备2插入值" bar"到表" table1"与PK" def456"
  4. 设备1下载设备2的事务日志并插入值" bar"到ID" def456"
  5. 设备2下载设备1的事务日志并插入值" foo"到ID" abc123"
  6. 这是有效的,因为设备知道事务将导致他插入使用设备特定值键入的行。因此,在插入操作之后,键列中没有重复值的危险。

    欢迎任何关于这种方法的想法!

    UPDATE 我将此标记为正确答案,因为它有效。以下是我如何修改现有数据库(和应用程序)以允许跨设备进行同步。幸运的是,这不是一个生产应用程序,所以对数据库进行的重大更改并没有引起问题。

    1. 更改所有数据库表以使用TEXT类型列作为其主键
    2. 添加"最后一个索引"表到数据库的表,该表以表名为键,并且有另一列显示添加到该表的最后一行的索引号
    3. 为app添加了一个方法,该方法通过检索表的最后插入索引并将其递增1来生成设备和行唯一TEXT键,然后将此设备的UUID添加到此处。
    4. 插入任何行时,调用(3)中描述的方法以获取用于将记录插入数据库的适当密钥
    5. 所有数据库修改函数都会导致SQL查询被添加到事务日志中,每个条目的日期和时间都标记在一起,并使用设备的UUID作为其文件名保存到本地文件
    6. 然后将设备的本地事务日志推送到iCloud
    7. 同步涉及以下内容:
      • 从iCloud下载所有交易日志
      • 忽略设备自己的事务日志,浏览每个日志中的SQL命令列表,并将它们添加到命令数组中,从上次同步时该日志的索引号开始
      • 将日志完成的索引号存储在数据库中,以便下次同步时不会重新执行相同的命令
      • 按日期排序所有日志中所有SQL命令的数组
      • 按顺序执行命令
    8. 关于这个过程的实现,我已经到了第5步。所有iCloud特定的东西都没有实现。但是,我已经通过在运行应用程序副本的设备之间手动复制事务日志来测试该过程,我可以确认该过程有效。包含设备的UUID的TEXT主键确保不会发生冲突。所有设备都可以插入彼此的数据,并且密钥始终是唯一的。

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

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