管理逻辑删除
逻辑删除表示已从副本中删除的项。逻辑删除主要用于帮助防止将已删除项重新引入副本中。为了避免潜在的性能或存储问题,必须定期清除逻辑删除。应仔细地管理此清除操作,以免重新引入已删除项。
表示逻辑删除
副本可以使用任何方法来跟踪已删除项。为了执行此任务,我们建议副本使用逻辑删除位或逻辑删除日志。
逻辑删除位
副本定义了项的元数据包含一个指示该项是否已从项存储区中删除的布尔值。当删除某项时,此值在该项的元数据条目中设置为 true。如果必须跟踪许多已删除项,则使用逻辑删除位对于存储而言效率较高,因为它对于每个项只要求一个附加位。这种方法对于枚举或清除逻辑删除而言效率较低,因为必须搜索整个元数据存储区。
逻辑删除日志
副本维护一个单独的日志,其中列出已从项存储区中删除的项。当删除某项时,将向逻辑删除日志中添加一个条目。如果必须跟踪许多已删除项,则使用逻辑删除日志对于存储而言效率较低,因为此日志对于每个已删除项都必须包含一个 ID。这种方法对于枚举或清除逻辑删除而言效率较高,因为列表只包含已删除项。
逻辑删除清除
同步社区中的每个副本只包含有关其自身状态的知识,而不包含有关任何其它副本的状态的知识。因此,将无法确定在整个社区中何时复制了某个逻辑删除。因此,对于任何特定副本,确定何时以及如何清除逻辑删除将完全根据本地情况决定。例如,可以基于本地时间戳或空间要求清除逻辑删除。副本可能具有一个策略,即逻辑删除占用的空间不能超过数据集的 10%。
在清除逻辑删除后,副本不了解此删除情况,而仍必须防止该项被引入其自己的存储区或其他副本中。为帮助防止出现此问题,将在副本的元数据存储区中保留每个项的创建版本和此副本的遗忘知识。当副本清除逻辑删除时,它必须在其遗忘知识中记录逻辑删除版本。
使用托管代码记录已清除的逻辑删除
若要记录已从副本的元数据存储区中删除某个已删除项的元数据,请对该副本的 ForgottenKnowledge 对象调用 ForgetTo。此方法需要已删除项的版本。
使用非托管代码记录已清除的逻辑删除
若要记录已从副本的元数据存储区中删除某个已删除项的元数据,请对于该副本的 IForgottenKnowledge 对象调用 IForgottenKnowledge::ForgetToVersion。此方法需要已删除项的版本。
向 Sync Framework 提供遗忘知识
如果副本通过使用遗忘知识跟踪已清除的逻辑删除,则其关联的提供程序必须将遗忘知识提供给需要此知识的 Sync Framework 方法,如 ChangeBatch(对于托管代码)或 IProviderSyncServices::CreateChangeBatch(对于非托管代码)。提供程序在同步期间还必须保存遗忘知识以及已更新的知识,例如,保存在其 StoreKnowledgeForScope 方法(对于托管代码)或 ISynchronousNotifyingChangeApplierTarget::SaveKnowledge 方法(对于非托管代码)中。
如果副本不清除逻辑删除且不维护遗忘知识,则其关联提供程序必须将 null(对于托管代码)或 NULL(对于非托管代码)传递到具有遗忘知识参数的 Sync Framework 方法。
与逻辑删除相关的方案
要考察的与逻辑删除相关的两个方案:一个正在请求同步的过期副本和一个向已删除项发送更新的副本。Sync Framework 同时检测这两个方案。
检测过期副本
在此方案中,目标副本相对于源副本已过期。因为源副本已清除了其逻辑删除,所以源副本不再了解删除情况。因此,源提供程序无法将表示这些删除的变更发送到目标提供程序。在应用变更之前,Sync Framework 将源副本的遗忘知识与目标副本的当前知识进行比较。如果目标知识不包含遗忘知识,Sync Framework 将目标副本识别为已过期并开始恢复同步。
如果应用程序已注册了事件处理程序,则 Sync Framework 将向应用程序提供继续或停止完全枚举的机会。在托管代码中,将激发 FullEnumerationNeeded 事件。在非托管代码中,应用程序将收到 ISyncCallback::OnFullEnumerationNeeded 回调。
如果应用程序尚未注册事件处理程序,将自动发生完全枚举。通过完全枚举,Sync Framework 可以将来自源提供程序的变更与目标副本中的项进行比较,以此确定必须从目标副本中删除哪些项。对于目标副本中的任何项,如果它在源提供程序中不具备对应的变更,则将从目标副本中删除此项。
检测对于已删除项的更新
在此方案中,源副本相对于目标副本已过期。如果自目标副本上次清除其逻辑删除以来源副本尚未同步,则会发生这种情况。如果在目标副本上删除某个项,随后从目标副本中清除该项的逻辑删除,并且对于源副本更新该相同项,则可能出现此问题。该项将出现在源提供程序向目标提供程序发送的变更批中。目标提供程序必须识别此项不是新项;否则,就会将该项错误地重新引入目标副本中。
请注意,将源副本中某项的当前版本与目标副本中的当前知识进行比较毫无意义,因为目标副本的当前知识中不包含可能重新引入的该项的当前版本。相反,应将源副本中该项的创建版本与目标副本中的当前知识进行比较,以确定目标副本是否先前已知道此项。因为在创建此项后肯定已删除了此项,并且目标副本的当前知识包含此删除,所以当前知识必然也包含此创建。
因此,在将新项添加到目标副本之前,Sync Framework 会将此项的创建版本与目标副本的当前知识进行比较。如果目标知识包括该项的创建版本,则目标副本先前已知道此项,但该项已被删除和遗忘。此项将被视为更新-删除冲突。
请参阅
参考
ISyncCallback::OnFullEnumerationNeeded
FullEnumerationNeeded