4

我正在使用 Google Gears 来离线使用应用程序(我知道 Gears 已弃用)。我面临的问题是与服务器上的数据库同步。

具体问题是主键或更准确地说是外键。在将信息发送到服务器时,我可以轻松地忽略主键,并生成新的主键。但是我怎么知道这些关系是什么。

我想到了一个解决方案,打赌我需要为每个客户保存所有的 pk。将多个客户端与一个服务器数据库同步的最佳方法是什么?

编辑:
我一直在考虑,我猜顺序主键不是最好的解决方案,但是还有什么其他的可能性呢?由于可能发生碰撞,基于时间的方法似乎不正确。

想到一个 GUID,这是一个选项吗?看起来在 javascript 中生成 GUID 并不是那么容易。

我可以用自然键或复合键做一些事情。正如我正在考虑的那样,这看起来是最好的解决方案。我可以期待任何问题吗?

4

4 回答 4

3

这不是一个完整的答案,但至少可以为您提供一些想法......

您提出的问题(以及您试图解决的问题)并非特定于 Google Gears,并且对于其他解决方案(如 HTML 5 或基于系统或 Flash/Air)仍然有效。


几个月前的上一次 ZendCon 上有一个关于这个主题的演讲——幻灯片可以在 slideshare 上找到:规划与浏览器本地数据库的同步


通过这些幻灯片,您会看到关于可能想到的几种可能性的注释(有些确实出现在您的脑海中,或者在其他答案中)

  • 使用 GUID
  • 复合键
  • 主键池(即预先保留一系列键)

当然,对于其中的每一个,都有优点......也有缺点——我不会复制粘贴它们:看看幻灯片;-)


现在,在您的情况下,哪种解决方案是最好的?很难说,实际上 - 越早考虑同步,它可能会更好/更容易:当应用程序仍处于设计阶段时,将内容添加到应用程序中要简单得多^^


首先,确定是否:

  • 您的应用程序通常已连接,并且很少发生断开连接
  • 或者,如果您的应用程序通常断开连接,并且仅偶尔连接一次。

那么,你要同步什么?

  • 数据 ?
    • 就像“这是该用户发出的所有命令的列表
    • 当然,在每个断开连接的设备上复制这些数据——每个设备都可以修改它
    • 在这种情况下,如果一个用户删除了一行,另一个用户添加了一行,如何知道哪一个拥有“真实”数据?
  • 或者对这些数据采取的行动?
    • 就像“我在该用户发出的命令列表中添加一个条目
    • 在这种情况下,如果一个用户删除了一行,而另一个用户添加了一行,那么同步很容易,因为您只需将这两个操作同步到您的中央数据库
    • 但这并不容易实现,尤其是对于大型应用程序/系统:每次执行操作时,您都必须记录它!


还有一个我们通常不会想到的特定问题 - 直到它发生:特别是如果您的同步过程可能需要一些时间(如果您有很多数据,如果您不经常同步,...) ,如果同步还没有完成就停止了怎么办?

例如,如果:

  • 火车上的用户可以使用一些 3G 卡访问网络
  • 同步开始
  • 有一条隧道 - 连接丢失。

在大多数情况下,拥有半同步数据可能不是那么好......

因此,您也必须找到解决该问题的方法:在大多数情况下,同步必须是原子的!

于 2010-03-12T22:45:40.227 回答
0

我想出了以下解决方案:

每个客户端都从服务器获得一个唯一的 ID。在引用主键的任何地方,我都使用带有客户端 ID 和自动增量字段的复合键。

这样,组合是独一无二的,并且很容易实现。剩下的唯一事情就是确保每个客户都获得一个唯一的 ID。

我刚刚发现了一个缺点:SQLite 不支持复合主键的自动增量,所以我必须自己处理 id。

于 2010-03-06T13:39:32.560 回答
0

我会使用与您的最新答案类似的设置。但是,为了解决您的自动增量问题,我将在您的主数据库中使用一个自动增量代理键,然后存储客户端主键和您的客户端 ID。这样,您就不会丢失或更改流程中的任何数据,并且您还可以跟踪数据最初来自哪个客户端。

请务必在您的 Client Pk、Client Id 上设置唯一索引,以启用任何子表的引用完整性。

于 2010-03-13T04:06:39.157 回答
0

客户端在断开连接时可以创建多少个对象是否有合理的限制?我可以看到的一种可能性是创建一种“本地序列”。

当您的客户端连接到中央服务器时,它会获得一个数字 ID,比如一个 7 位数字(服务器将其生成为一个序列)。

实际的 PK 创建为如下字符串:895051|000094 或 895051|005694 其中第一部分是从服务器发送的 7 位数字,第二部分是由客户端管理的“本地”序列。

与中央同步后,您可以获得一个新的 7 位数字并重新启动本地序列。总而言之,这与您提出的建议没有太大不同。它只是使实际的 PK 完全独立于客户端身份。

另一个好处是,如果您遇到客户端从未连接到服务器的情况,它可以在本地使用 000000|000094,需要来自服务器的新号码并更新其侧的密钥,然后再发送回服务器进行同步(如果你有很多 FK 约束,这很棘手,而且不可能)。

于 2010-03-13T12:29:19.990 回答