我正在构建一个iOS应用程序,用于(创建,编辑)与服务器数据库同步的记录(在sqlite中)。如果应用程序中的记录已从服务器下载然后在本地修改,我正在制作副本,因为我希望能够恢复到服务器版本。因此,对于给定的记录ID,我有时可以有两个副本(服务器,本地)。我在设计数据库布局方面寻求帮助。
最初,我使用了两个表 - 一个用于存储服务器记录(通过同步到达),另一个用于存储本地修改/本地创建(尚未同步)的记录。我发现这种方法很麻烦,因为(a)我需要进行聚合搜索(选择优先考虑本地修改副本的记录),(b)我需要将数据从一个表移动到另一个表,这听起来不像一个好的做法,(c)模式非常复杂(数百列)并且难以保持两个表模式同步。
然后我将所有内容合并到一个表中,添加状态列(服务器/本地)。这似乎很好,直到我意识到过滤重复记录(存在服务器和本地副本的那些记录)的复杂程度。计算,搜索,选择所需的10行复杂查询(由于sqlite的限制) - 请参阅我的其他问题here和here。
我正在考虑将所有内容保存在一个表中,但放弃状态列,并创建一个单独的表来跟踪状态,每个记录一行,如下所示:
数据:
id recordID name col2 col3 ...
1 1001 Server record, not changed locally xxxx xxxx ...
2 1002 Server record changed locally xxxx xxxx ...
3 1002 Server record changed locally xxxx yyyy ...
4 1003 Record created locally xxxx xxxx ...
5 1004 Server record changed locally xxxx xxxx ...
6 1004 Server record changed locally xxxx yyyy ...
状态跟踪:
id recordID server local
1 1001 1
2 1002 2 3
3 1003 4
4 1004 5 6
聚合上述信息以显示将意味着显示本地记录(如果有)或其他服务器记录 - 在这种情况下,数据行1,3,4和6.在这种情况下,我的查询将更简单(只是与案件的联合)。
这是最好的方法,还是我应该使用更好的设计?
答案 0 :(得分:1)
我将摆脱本地/服务器状态字段并引入时间戳/版本字段,一旦双方中的一方改变记录,该字段将设置为当前日期。因此,您始终知道哪些行是最新记录(具有最高时间戳的记录)。为了恢复旧版本功能,我考虑提供退回/转发记录的一个版本的选项。如果用户选择了一个旧版本来恢复,我将使用当前时间戳保存该版本的新副本。
您可以通过在协议上传输全部或部分(未知时间戳)记录来实现轻松同步。考虑在客户端和服务器端转储给定表的时间戳列表,比较增量上的列表并为另一方准备插入语句。瞧,同步完成。您唯一需要考虑的是您不更新行,而是创建带有新时间戳的新版本。
这是数据仓库系统中的最佳实践。 (没有更新哲学)
如果您发现每条记录有大量版本,如果有N个较新版本,您可能会定期丢弃最旧的记录。