【问题标题】:Synchronize two databases primary keys without atomicity无原子性同步两个数据库主键
【发布时间】:2015-10-26 10:57:38
【问题描述】:

考虑两个数据库 A 和 B,它们的行具有一个公共主键 (PK)。两个数据库都只能通过函数return all keys of items [X,Y[查询。键是非顺序的,因此这个查询可以返回,例如

>>> get_Akeys(0, 5)
>>> [20, 21, 23, 24, 25]
>>> get_Bkeys(0, 5)
>>> [20, 21, 23, 24, 25]

随着时间的推移,数据库 A 会发生变化(B 不会):它有行添加(始终带有增量 PK)和行删除(任何有效的 PK)。目的是使数据库 B 与 A 保持同步。为此,可以将行 A - B(设置减法)添加到数据库 B,并删除行 B - A

很遗憾,我们无法访问完整的数据库 A:get_Akeys(0, 10**10) 形式的查询被禁止,因为 |A|太大。因此,一种策略是将其切碎,例如getA(i) = get_Akeys(i*N, (i + 1)*N) 其中N为常数,依次查询。

但是,这会破坏请求的原子性:考虑 A = [20,21,22,25,26,27,28]B = [20,21,22,25,26,27]N = 3 以及这一系列事件:

  1. getA(0) == [20,21,22] == getB(0)(全部正确)
  2. A.delete_key(22) # getA(0) becomes [20,21,25]
  3. getA(1) == [26,27,28] != [25,26,27] == getB(1)

在 3. 中,结果意味着应该从 B 中删除元素 25(错误),并且应该添加元素 28(正确)。

关于如何使用上述约束同步两个数据库的任何想法?

在我的用例中,每个 getA 需要约 1 分钟来获取我正在使用的 N,获取所有条目需要约 100 次查询 N/|A|我正在使用,同步可能需要 2 天才能完成。

【问题讨论】:

标签: database algorithm


【解决方案1】:

不是将getA() 限制为最多返回一个固定 个键,而是将其限制为返回特定范围内的一组键。然后你永远不会得到# getA(0) becomes [20,21,25]:在A.delete_key(22)运行之后,getA(0) = [20,21]。 25 仍属于下一组。

根据您的定义(“返回项目的所有键 [X,Y[”, “getA(i) = get_Akeys(i*N, (i + 1)*N”),这就是您必须要做的事情,所以我很困惑是什么问题。

【讨论】:

  • 为了获得更多确定性的结果,我建议:查询A 获取N 元素,然后查询B 以获取A 中的ID 范围,如j_random_hacker 建议的那样.
  • @TomerW:我认为这有时会忘记将删除从 A 传递到 B:假设我们要求 A 中的前 1000 个元素,然后更新 B 以匹配,然后调用 A.delete_key(42)。如果我们现在要求 A 中的第二个 1000 个元素(以便继续使 B 保持最新),那么这个查询和任何未来的查询都不会在 A 中找到第 1001 个键,所以如果它不在 B 中,那么 B 将永远存在过时了。编辑:或者这不是你的建议?
  • 我无法执行您建议的查询;数据库 A 对我来说是外部的,我在问题中写的是我能做的唯一查询;具体来说,我通过 GET 访问 db A,而 GET 中只有参数 items=[a,b] 我封装在 get_Akeys 中以简化此处。
  • @J.C.Leitão:我现在看到XY 是行的位置索引,而不是键。 (您的第一个代码 sn-p 建议了正确的解释,但更明确一点会有所帮助。)您是否有办法检测何时执行对 A 的删除?如果你这样做了,那么总是比简单的线性扫描更早地开始对 A nDeletionsSoFar 行的查询就足够了;如果没有,我认为没有通用、有效的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多