我正在构建一个模块来编辑节点层次结构。您可以将其视为具有多级嵌套目录和文件的非常大的目录结构。层次结构的节点存储在关系数据库表中。唯一的区别是没有文件夹/目录这样的东西。所有节点都具有相同的特征。因此,节点的父节点也是节点。并且只有一个根节点,一个节点只能有一个父节点,因此没有多层次结构。
表格列
node_id [bigint] not null
name [nvarchar(50)]
parent_node_id [bigint]
leaf_node [bit]
目标是找出一种方法来编辑一个层次结构,而无需用户踩到彼此的脚趾。我们要么必须设计版本控制架构来解决冲突,要么使用一些锁定机制(悲观或乐观)来防止其他人编辑整个层次结构中某个给定父节点的祖先(或子树)的一部分的节点树。如果我们执行锁定,那么使用编辑器的每个人都需要不断刷新他们的树以查看其他人的更改。
只有三个功能需要担心。仅允许一个用户在主树中编辑节点/对象。将新创建的子树拖放到主树中。将主树中的子树拖放到主树中的另一个节点,从而使删除的子树成为该节点的子节点。
我认为这种架构与管理文件夹和文件的操作系统架构不同。这通常是如何通过数千名用户完成的?我宁愿使用锁定机制而不是使用版本控制来降低其复杂性。我只是不确定最好的方法是什么。
到目前为止,这是我的计划:
如果正在编辑节点,请不要锁定它,直到保存发生并且数据库即将更新记录。数据库进行更改后,将其解锁。如果其他人尝试在数据库进行更改的同时编辑记录,请不要告诉用户它已被锁定。让数据库处理记录/节点上的锁定。
如果将新子树拖入主树父节点,则锁定新父节点。然后插入新记录并更新根父级以指向主树父节点。然后通知所有客户端更新其主树。因此,在丢弃发生后,所有锁定都发生在数据库端。
如果将现有主树父节点拖入现有主树父节点并成为子节点,则应锁定旧父节点(成为新子节点)并锁定新父节点。然后更新新子节点的父节点。然后更新所有客户端(所有用户)并更新其主树。因此,在丢弃发生后,所有锁定都发生在数据库端。
答案 0 :(得分:0)
对于1你可以使用乐观锁。 (您当前的方法意味着“最后数据覆盖现有”)。
关于2和3 - 似乎只需重新链接节点即可实现拖放,因此您可以更轻松地实现拖放 - 无需过多的数据复制。
在这种情况下,您可以引入一个link lock
,它会锁定两个链接端。这可以防止“源”节点同时移动到某个其他“目的地”节点;它也可以防止突然的“目的地”节点移动,这对客户来说应该是一个惊喜。