将 SQLite3 数据库与 iCloud 同步
Sync SQLite3 database with iCloud
这个问题已经被问过很多次了,但我一直找不到完整的答案。我需要使用 sqlite3 数据库在我的应用程序中存储数据,核心数据不是一个选项。我想使用 iCloud 跨设备同步数据,最好的方法似乎是将 SQL 事务日志发送到 iCloud 并使用它们使设备保持最新。目前我想出的过程如下:
- 所有数据库更改查询(INSERT、UPDATE、DELETE)一旦执行都存储在事务数组中,每个元素包含 sql 查询和执行的时间戳
- 数据库包含一个 table 用于记录应用程序最后到达的交易数组中的点(包括存储在 iCloud 上的交易文件的文件名)
- 交易数组保存到 iCloud 上的设备唯一文件
- 同步时:
- 从 iCloud 获取交易文件数组
- 创建要提交的空事务数组
- 对于每个文件:
- 检查数据库以获取交易文件中的最后位置
- 如果none,从文件开头开始
- 将每个事务从该点添加到要提交的事务数组
- 用交易文件的新最后位置更新数据库,这样同步的交易就不会重复
- 按事务时间戳对要提交的事务数组进行排序
- 执行要提交的事务数组中的命令
我相信我可以将数据拉到每台设备并执行更新每个本地副本的命令。我设想的唯一问题是,如果两个设备在离线时向同一个 table 插入一条记录,然后同步。例如:
- 设备 1 和设备 2 都有同步的数据库副本,table "table1"
中各有 4 条记录
- 设备 1 使用 PK 5
将值 "foo" 插入到 table "table1"
- 设备 2 使用 PK 5
将值 "bar" 插入到 table "table1"
- 设备 1 下载设备 2 的事务日志并将值 "bar" 插入 ID 6
- 设备 2 下载设备 1 的事务日志并将值 "foo" 插入 ID 6
我们现在遇到的情况是,这些记录的主键在每台设备上都颠倒了,这将破坏与 table 依赖主键进行链接的链接。
我仍在努力研究解决此问题的方法,但与此同时,如果有人有任何建议,我将不胜感激!
我整天都在考虑这个问题,我想我已经想出了一个解决方案。我贴在这里看看有没有人有什么意见,明天我会去实现它。
我的想法是取消自动递增的整数主键,并用基于字符串的键替换它。密钥将从设备的 UUID 和时间戳生成。这意味着键是设备特定的并且行是唯一的。因此,要使用此方法重述上面的 INSERT 示例(使用简化的键字符串以便于阅读):
- 设备 1 和设备 2 都有同步的数据库副本,table "table1"
中各有 4 条记录
- 设备 1 使用 PK "abc123"
将值 "foo" 插入到 table "table1"
- 设备 2 使用 PK "def456"
将值 "bar" 插入到 table "table1"
- 设备 1 下载设备 2 的事务日志并将值 "bar" 插入 ID "def456"
- 设备 2 下载设备 1 的事务日志并将值 "foo" 插入 ID "abc123"
这是可行的,因为设备知道事务将导致插入使用设备特定值键入的行。因此在插入操作后键列中没有重复值的危险。
欢迎对这种方法提出任何想法!
更新
我将其标记为正确答案,因为它有效。以下是我修改现有数据库(和应用程序)以允许跨设备同步的方法。幸运的是,这还不是一个生产应用程序,因此所需的对数据库的重大更改没有造成问题。
- 更改所有数据库 table 以使用 TEXT 类型列作为它们的主键
- 将 "last index" table 添加到数据库,该数据库以 table 名称作为键,并且还有一列显示添加到该 [= 的最后一行的索引号82=]
- 向应用程序添加了一种方法,该方法通过检索 table 的最后插入索引并将其递增 1,然后将设备的 UUID 添加到此生成设备和行唯一的 TEXT 键。
- 插入任何行时,调用(3)中描述的方法获取适当的键,用于将记录插入数据库
- 所有数据库修改函数都会导致 SQL 查询被添加到事务日志中,其中的每个条目也带有日期和时间戳,并使用设备的 UUID 作为文件名保存到本地文件中
- 然后将设备的本地事务日志推送到 iCloud
- 同步涉及以下内容:
- 从 iCloud 下载所有交易日志
- 忽略设备自己的事务日志,浏览每个日志中的 SQL 命令列表,并将它们添加到命令数组中,从上次同步时该日志的索引号开始
- 将日志的索引号存储在数据库中,以便在下一次同步时不会重新执行相同的命令
- 按日期
对所有日志中所有 SQL 命令的数组进行排序
- 按顺序执行命令
关于这个过程的实现,我已经进行到第 5 步了。None iCloud 特定的东西已经实现了。但是,我已经通过在设备 运行 应用程序副本之间手动复制事务日志来测试该过程,并且我可以确认该过程有效。包含设备 UUID 的 TEXT 主键确保不会发生冲突。所有设备都可以插入彼此的数据,密钥永远是唯一的。
这样做的缺点是数据库会更大(因为键比整数长),查询可能需要更长的时间,因为涉及到很多字符串比较。但是,我使用的数据库相对较小,每次用户交互只有几个查询,所以我预计不会出现问题。
我希望这对遇到同样问题的其他人有用:)
这个问题已经被问过很多次了,但我一直找不到完整的答案。我需要使用 sqlite3 数据库在我的应用程序中存储数据,核心数据不是一个选项。我想使用 iCloud 跨设备同步数据,最好的方法似乎是将 SQL 事务日志发送到 iCloud 并使用它们使设备保持最新。目前我想出的过程如下:
- 所有数据库更改查询(INSERT、UPDATE、DELETE)一旦执行都存储在事务数组中,每个元素包含 sql 查询和执行的时间戳
- 数据库包含一个 table 用于记录应用程序最后到达的交易数组中的点(包括存储在 iCloud 上的交易文件的文件名)
- 交易数组保存到 iCloud 上的设备唯一文件
- 同步时:
- 从 iCloud 获取交易文件数组
- 创建要提交的空事务数组
- 对于每个文件:
- 检查数据库以获取交易文件中的最后位置
- 如果none,从文件开头开始
- 将每个事务从该点添加到要提交的事务数组
- 用交易文件的新最后位置更新数据库,这样同步的交易就不会重复
- 按事务时间戳对要提交的事务数组进行排序
- 执行要提交的事务数组中的命令
我相信我可以将数据拉到每台设备并执行更新每个本地副本的命令。我设想的唯一问题是,如果两个设备在离线时向同一个 table 插入一条记录,然后同步。例如:
- 设备 1 和设备 2 都有同步的数据库副本,table "table1" 中各有 4 条记录
- 设备 1 使用 PK 5 将值 "foo" 插入到 table "table1"
- 设备 2 使用 PK 5 将值 "bar" 插入到 table "table1"
- 设备 1 下载设备 2 的事务日志并将值 "bar" 插入 ID 6
- 设备 2 下载设备 1 的事务日志并将值 "foo" 插入 ID 6
我们现在遇到的情况是,这些记录的主键在每台设备上都颠倒了,这将破坏与 table 依赖主键进行链接的链接。
我仍在努力研究解决此问题的方法,但与此同时,如果有人有任何建议,我将不胜感激!
我整天都在考虑这个问题,我想我已经想出了一个解决方案。我贴在这里看看有没有人有什么意见,明天我会去实现它。
我的想法是取消自动递增的整数主键,并用基于字符串的键替换它。密钥将从设备的 UUID 和时间戳生成。这意味着键是设备特定的并且行是唯一的。因此,要使用此方法重述上面的 INSERT 示例(使用简化的键字符串以便于阅读):
- 设备 1 和设备 2 都有同步的数据库副本,table "table1" 中各有 4 条记录
- 设备 1 使用 PK "abc123" 将值 "foo" 插入到 table "table1"
- 设备 2 使用 PK "def456" 将值 "bar" 插入到 table "table1"
- 设备 1 下载设备 2 的事务日志并将值 "bar" 插入 ID "def456"
- 设备 2 下载设备 1 的事务日志并将值 "foo" 插入 ID "abc123"
这是可行的,因为设备知道事务将导致插入使用设备特定值键入的行。因此在插入操作后键列中没有重复值的危险。
欢迎对这种方法提出任何想法!
更新 我将其标记为正确答案,因为它有效。以下是我修改现有数据库(和应用程序)以允许跨设备同步的方法。幸运的是,这还不是一个生产应用程序,因此所需的对数据库的重大更改没有造成问题。
- 更改所有数据库 table 以使用 TEXT 类型列作为它们的主键
- 将 "last index" table 添加到数据库,该数据库以 table 名称作为键,并且还有一列显示添加到该 [= 的最后一行的索引号82=]
- 向应用程序添加了一种方法,该方法通过检索 table 的最后插入索引并将其递增 1,然后将设备的 UUID 添加到此生成设备和行唯一的 TEXT 键。
- 插入任何行时,调用(3)中描述的方法获取适当的键,用于将记录插入数据库
- 所有数据库修改函数都会导致 SQL 查询被添加到事务日志中,其中的每个条目也带有日期和时间戳,并使用设备的 UUID 作为文件名保存到本地文件中
- 然后将设备的本地事务日志推送到 iCloud
- 同步涉及以下内容:
- 从 iCloud 下载所有交易日志
- 忽略设备自己的事务日志,浏览每个日志中的 SQL 命令列表,并将它们添加到命令数组中,从上次同步时该日志的索引号开始
- 将日志的索引号存储在数据库中,以便在下一次同步时不会重新执行相同的命令
- 按日期 对所有日志中所有 SQL 命令的数组进行排序
- 按顺序执行命令
关于这个过程的实现,我已经进行到第 5 步了。None iCloud 特定的东西已经实现了。但是,我已经通过在设备 运行 应用程序副本之间手动复制事务日志来测试该过程,并且我可以确认该过程有效。包含设备 UUID 的 TEXT 主键确保不会发生冲突。所有设备都可以插入彼此的数据,密钥永远是唯一的。
这样做的缺点是数据库会更大(因为键比整数长),查询可能需要更长的时间,因为涉及到很多字符串比较。但是,我使用的数据库相对较小,每次用户交互只有几个查询,所以我预计不会出现问题。
我希望这对遇到同样问题的其他人有用:)