我正在处理页面层次结构(mongodb 文档):
{
_id: 012,
content: "lorem ipsum whatever...",
subpages: [123,234,345,456], // page ids
}
页面结构实际上是高度动态的,因此许多更新将与许多读取同时发生。但是,每次更改(例如将子页面移动到另一个页面)都需要至少 2 次更新操作:
// move 123 into page 234
db.pages.update({"_id":012}, {$pull:{"subpages":123}});
db.pages.update({"_id":234}, {$push:{"subpages":123}});
// delete page 345
db.pages.update({"_id":012}, {$pull:{"subpages":345}});
db.pages.remove({"_id":345});
有没有办法执行(或设计模型以启用执行)操作,例如移动页面或原子地删除页面(以防止层次结构的状态变坏)?
笔记
我现在正在研究的一种可能性是通过向每个页面添加一个“lockedBy”字段来手动锁定文档,该字段将包含一个事务 ID。但是如果我想要第二个锁定操作阻塞直到第一个锁定操作完成,我不喜欢连续轮询的想法(请参阅https://jira.mongodb.org/browse/SERVER-2244)。此外,由于锁定是由应用程序管理的,如果应用程序(或其中一个实例)在锁定操作期间由于某种原因出现故障,则需要以某种方式解锁文档,而不会影响其他事务。
我还查看了http://www.mongodb.org/display/DOCS/Trees+in+MongoDB,似乎没有一个示例(除了单个文档)解决了这个问题。但是,我想避免将整个层次结构放入单个文档中,因为 16MB 的文档大小限制和移动页面的困难(基本上我需要为每次更改更新整个文档)。
更新
我们希望一个页面最多支持 10000 个子页面。页面 ID 的长度至少为 6 个字符。考虑到这一点,我们离开了 mySQL,因为我们需要跟踪子页面的顺序。由于 mySQL 没有数组结构,唯一的方法是使用位置列。当页面频繁移动时,计算平均位置并在位置值变得太长时重新索引是很昂贵的。此外,如果我们想将逗号分隔的 id 列表放入列中,我们必须使用 TEXT 列(从磁盘读取)而不是 VARCHAR(限制为 65536 个字符)以支持 10000 个子页。