"墓碑" 文件
墓碑文档是在删除原始文档时保存在数据库中的小文档。 它们的目的是允许复制删除。
当复制完成时,不再需要墓碑。 自动压缩有助于确保在复制期间仅保留和传输最小数量的数据。 但是,墓碑文档不会自动除去。
随着时间的推移,随着文档的创建和删除,墓碑文档的数量会增加。 每个墓碑都很小,但渐渐地它们增加了数据库磁盘空间使用量,并增加了主索引的查询时间。 为了减少这些影响,您可能想要除去墓碑。
简单删除 "墓碑" 文件
要手动除去墓碑,请执行以下步骤:
- 创建数据库以保存所需文档。
新数据库旨在存放除墓碑文件以外的所有文件。
- 设置 过滤复制 以将文档从原始数据库复制到新数据库。
配置过滤器,以便不复制具有 "_deleted
" 属性的文档。
-
复制完成后,切换应用程序逻辑以使用新数据库。
-
验证应用程序是否与新数据库一起正常工作。
当您确信所有内容都正常工作时,您可能希望删除旧数据库。
通常,请尝试设计并实施应用程序以执行最低必要删除量。
请参阅示例过滤器以在复制期间排除已删除的文档:
{
"_id": "_design/filters",
"filters": {
"deleted_filter": "function(doc, req) { return !doc._deleted; };"
}
}
墓碑文件的高级删除
如果在执行复制期间未在源数据库中更新文档,那么 简单除去方法 将正常工作。
如果在复制期间进行了更新,那么可能将完整文档照常复制到目标数据库,并且还会从源数据库中删除该文档,从而留下墓碑。 问题是未将墓碑复制到目标数据库,因为过滤器排除了墓碑。 因此,不会从目标数据库中删除已从源数据库中删除的文档,这将导致不一致。
解决方案是使用 validate_doc_update
函数更高级地除去墓碑。
validate_doc_update
函数存储在设计文档中。 每次在数据库中更新文档时,都会运行此函数。 该功能可用于防止无效或未经授权的文档更新。
该函数通过使用以下参数来工作:
- 新版本的文档。
- 数据库中文档的当前版本。
- 用户上下文,提供有关提供更新文档的用户的详细信息。
该函数检查请求以确定是否允许更新继续。 如果可接受更新,那么此函数将返回。 如果更新不可接受,那么将返回适当的错误对象。 特别是,如果用户无权进行更新,那么将返回 unauthorized
错误对象以及说明错误消息。 同样,由于某些原因 (例如,新文档中没有某些必填字段时) ,可能不允许所请求的更新。 在这种情况下,将返回 forbidden
错误对象,并再次返回说明错误消息。
对于墓碑移除,合适的 validate_doc_update
函数将按如下所示工作:
- 如果更新要将更改应用于目标数据库中的现有文档 (
oldDoc
) ,那么此函数允许通过返回进行更改。
原因是更新影响了在复制期间复制到目标数据库的文档,但在复制期间在源数据库中更改了该文档。 可能是更改为 DELETE
,从而在目标数据库中生成墓碑记录。 墓碑记录将在未来某个时间由后续复制过程移除。 2. 目标数据库没有当前文档的副本,要更新的文档具有 _deleted
属性 (指示它是墓碑)。 因此,更新的文档必须是墓碑,并且之前迂到过,因此必须拒绝对目标数据库的更新。
请参阅示例 JavaScript validate_doc_update
函数以拒绝目标数据库中尚未存在的已删除文档:
function(newDoc, oldDoc, userCtx) {
// any update to an existing doc is OK
if(oldDoc) {
return;
}
// reject tombstones for docs we don’t know about
if(newDoc["_deleted"]) {
throw({forbidden : "Deleted document rejected"});
}
return; // Not strictly necessary, but clearer.
}
要使用 validate_doc_update
函数来除去墓碑文档,请执行以下操作:
- 停止从源到目标数据库的复制。
- 如果适用,请删除目标数据库,然后创建新的目标数据库。
- 添加合适的
validate_doc_update
函数,类似于提供的示例。 - 将其添加到目标数据库中的设计文档。
- 重新启动源与 (新) 目标数据库之间的复制。
- 复制完成后,切换应用程序逻辑以使用新数据库。
- 验证应用程序是否与新数据库一起正常工作。
当您确信所有内容都正常工作时,您可能希望删除旧数据库。
以下是使用 validate_doc_update
函数来除去墓碑文档 (如果可能) 的另一个变体。
- 向墓碑文档添加一些元数据,例如,用于记录删除日期。
- 使用此函数来检查元数据并允许删除文档 (如果必须将这些文档应用于目标数据库)。
此检查有助于确保正确复制删除。
墓碑去除的性能影响
墓碑用于从数据库中更一致地删除文档。 此目的对于移动设备尤其重要: 如果没有墓碑文档,那么删除操作可能无法正确复制到移动设备,从而导致文档可能永远不会从设备中删除。
如果您重新创建数据库,例如复制的新目标。 任何将目标数据库用作服务器的客户机都必须再次处理所有更改,因为数据库序号可能不同。
如果您正在使用 validate_doc_update
函数,请避免将该函数复制到客户机。 此规则用于防止由于在客户机上存在该函数而产生不需要的副作用的可能性。
IBM Cloudant 同步 库不会复制设计文档,因此 validate_doc_update
函数的复制通常不是 IBM Cloudant的问题。 但是,其他客户机可能会复制设计文档或 validate_doc_update
功能,从而可能产生不需要的副作用。