安全组合权限下的分布式查询处理:第三方参与与安全查询计划构建
1. 第三方参与
在分布式查询处理中,连接操作的执行必然涉及操作数之间的信息通信,我们会根据权限(基本权限或组合权限)来检查这种通信,只有在授权的情况下才允许进行。有时,对于给定的连接操作,四种可能的执行模式都无法对应安全的分配。在这种情况下,我们设想第三方可以参与操作,它可以作为两个操作数之一的代理,或者作为它们的协调者。
以下是第三方参与的不同方式总结:
| 模式 | 描述 |
| ---- | ---- |
| [St,NULL] | 第三方接收操作数的关系,并独立计算(常规)连接。 |
| [St,Sl] 和 [St,Sr] | 第三方在计算中分别用 Sl(Sr)替换 Sr(Sl)的角色,其中 Sl(Sr)作为从节点,第三方作为主节点。 |
| [Sl,St] 和 [Sr,St] | 第三方在计算中分别用 St 替换 Sr(Sl)的从节点角色,Sl(Sr)作为主节点。 |
| [St,SlSr] | 第三方担任主节点,负责计算连接,Sl 和 Sr 都作为从节点。每个操作数计算参与连接的属性投影并发送给第三方,第三方计算两个输入之间的连接并将结果返回给每个操作数,操作数将输入与自身关系连接后返回给第三方,第三方再连接从操作数收到的关系并计算最终结果。 |
需要注意的是,前五种场景是之前场景的简单改编,第三方仅作为代理,因此需要有查看其代理方关系的必要权限,以及其角色(主/从)所需的视图。而 [St,SlSr] 场景则更复杂,第三方只需查看参与连接的操作数元组,每个从节点只需查看与自身连接的其他关系的属性。
考虑到第三方的参与,需要对执行器分配定义进行微调:
定义 5.18(包含第三方的执行器分配)
:给定查询计划 T(NT,ET),执行器分配函数 εT : NT →S ×{S ∪[S ×S ]∪NULL} 是将服务器对分配给节点的一种方式,满足以下条件:
1. 每个叶节点(对应关系 R)分配对 [S, NULL],其中 S 是存储 R 的服务器。
2. 每个非叶节点 n,对应服务器 Sl 上操作数 Rl(左子节点)的一元操作 op,分配对 [Sl,NULL]。
3. 每个非叶节点 n,对应服务器 Sl 上操作数 Rl(左子节点)和服务器 Sr 上操作数 Rr(右子节点)的连接操作,分配对 [主节点, 从节点],其中主节点 ∈S,从节点 ∈{S ∪[Sl,Sr]∪NULL},主节点 ≠ 从节点,且至少有一个元素在 {Sl,Sr,[Sl,Sr],NULL} 中。
安全分配和可行查询计划的定义保持不变。
示例 5.6 :考虑特定场景和服务器存储数据的权限。(Employee◃▹Patient) 和 Treatment 之间的外连接既不能安全地分配给 SE 和 SP,也不能分配给 ST。因此,需要第三方介入。具体来说,该操作的安全分配是 [SP,SD]。因为 SD 有权访问 Treatment 关系的 SSN、Type 和 Duration 属性,以及 Employee 与 Patient 连接后的 SSN、DoB 和 Race 属性。SP 有权在连接条件 P.SSN=T.SSN 成立的情况下查看整个 Treatment 关系。
我们可以将问题表述如下:
问题 5.1
:给定查询计划 T(NT,ET) 和一组权限 P:1) 确定 T 是否可行;2) 为其获取安全分配 εT。
2. 构建安全查询计划
为了最小化计算成本,安全分配的确定遵循两个基本原则:
- 优先选择半连接(而非常规连接)。
- 如果有多个服务器可以安全地执行连接操作(在树的给定级别),我们优先选择参与更多连接操作的服务器。为此,我们为每个候选服务器关联一个计数器,用于跟踪该服务器作为候选的连接操作数量。
以下是计算查询计划安全分配的算法:
INPUT
P
G(N ,e)
T(NT,ET)
OUTPUT
εT (n) /* as n.executor */
/* n.left, n.right: left and right children */
/* n.operator, n.parameter: operation and its parameters */
/* [n.π,n.◃▹,n.σ]: profile */
/* n.leftslave, n.rightslave: left and right slaves */
/* n.leftthirdslave: third party acting as left slave */
/* n.rightthirdslave: third party acting as right slave */
/* n.candidates: list of records of the form [server,fromchild,counter] stating candidate servers, the child
(left, right) it comes or proxies for, and the number of joins for which the server is candidate in the subtree */
/* n.executor.master, n.executor.slaves: executor assignment */
MAIN
FindCandidates(root(T))
AssignExecutor(root(T), NULL)
return(T)
该算法通过对查询树计划进行两次遍历工作:
1.
第一次遍历(FindCandidates 过程)
:以后序遍历方式访问树。在每个节点,根据子节点的配置文件和与该节点关联的操作计算该节点的配置文件。同时,根据子节点的可能候选集确定该节点的可能候选分配集。
- 如果节点是一元操作,该节点的候选集是其唯一子节点的所有候选集。
- 如果节点是连接操作,FindCandidates 过程在需要验证特定服务器是否可以作为主节点、从节点或计算常规连接时调用 Authorized 函数。Authorized 函数在表示操作执行中应可见视图配置文件的视图图上调用。算法按连接计数器递减顺序考虑左子节点的候选集,直到找到第一个可以作为左从节点的候选集。然后,算法检查右子节点的所有候选集,以确定它们是否可以作为半连接的主节点(如果找到左从节点)或常规连接的主节点(如果未找到左从节点)。对于每个这样的服务器候选集,将三元组 [服务器, 右, 计数器] 添加到候选列表中,计数器比该服务器在子节点级别执行的连接数多一个。最后,算法对称地确定右子节点中是否有可以作为从节点的候选集,然后确定所有可以作为主节点的左候选集,并将它们添加到候选集中。如果没有找到候选集,算法调用 FindThirdParty 函数来确定是否可以通过第三方介入计算该操作。如果仍然没有返回任何候选集,算法退出并返回无法进行安全分配的节点,表示树不可行。
2.
第二次遍历(AssignExecutor 过程)
:以先序遍历方式递归访问树。在根节点,如果有多个可能的分配,选择连接计数最高的候选服务器。然后,将选择的候选服务器向下推到在前序遍历中确定它的子节点。另一个子节点(如果存在)则推送记录的候选从节点。如果没有记录到可能的从节点(即 right - slave/left - slave = NULL 或从节点是第三方),则推送 NULL 值。在每个子节点,主执行器确定为父节点推送的服务器(如果不为 NULL)或连接计数最高的候选服务器,并递归重复该过程,直到到达叶节点。
以下是 FindCandidates 函数的具体实现:
FINDCANDIDATES(n)
l := n.left
r := n.right
if l ̸=NULL then FindCandidates(l)
if r ̸=NULL then FindCandidates(r)
case n.operator of
π: n.π := n.parameter; n.◃▹:= l.◃▹; n.σ := l.σ
for c in l.candidates do Add [c.server, left, c.count] to n.candidates
σ: n.π := l.π; n.◃▹:= l.◃▹; n.σ := l.σ ∪n.parameter
for c in l.candidates do Add [c.server, left, c.count] to n.candidates
◃▹: n.π := l.π ∪r.π; n.◃▹:= l.◃▹∪r.◃▹∪n.parameter; n.σ := l.σ ∪r.σ
right slave view := [Jl, l.◃▹, l.σ]
left slave view := [Jr, r.◃▹, r.σ]
right master view := [l.π ∪Jr, l.◃▹∪r.◃▹∪n.parameter, l.σ ∪r.σ]
left master view := [Jl ∪r.π, l.◃▹∪r.◃▹∪n.parameter, l.σ ∪r.σ]
right full view := [l.π, l.◃▹, l.σ]
left full view := [r.π, r.◃▹, r.σ]
/* check case [Sr,NULL] and [Sr,Sl] */
n.leftslave := NULL
c := GetFirst(l.candidates)
while (n.leftslave=NULL)∧(c̸=NULL) do
if Authorized(Gleft slave view, c.server) then n.leftslave := c
c := c.next
regular := NULL
rightmasters = NULL
for c in r.candidates do
if Authorized(Gright full view, c.server) then Add [c.server, right, c.count+1] to regular
if Authorized(Gright master view, c.server) then Add [c.server, right, c.count+1] to rightmasters
if n.leftslave̸=NULL then
Add rightmasters to n.candidates
else
Add regular to n.candidates
/* check case [Sl,NULL] and [Sl,Sr] */
n.rightslave := NULL
c := GetFirst(r.candidates)
while (n.rightslave=NULL)∧(c̸=NULL) do
if Authorized(Gright slave view, c.server) then n.rightslave := c
c := c.next
regular := NULL
leftmasters = NULL
for c in l.candidates do
if Authorized(Gleft full view, c.server) then Add [c.server, left, c.count+1] to regular
if Authorized(Gleft master view, c.server) then Add [c.server, left, c.count+1] to leftmasters
if n.rightslave̸=NULL then
Add leftmasters to n.candidates
else
Add regular to n.candidates
/* check third party */
if n.candidates=NULL then n.candidates := FindThirdParty(n,leftmasters,rightmasters)
/* node cannot be executed */
if n.candidates=NULL then exit(n)
以下是 AssignExecutor 函数的具体实现:
ASSIGNEXECUTOR(n, from parent)
if from parent̸=NULL then
chosen := Search(from parent, n.candidates)
else
chosen := GetFirst(n.candidates)
n.executor.master := chosen.server
case chosen.fromchild of
left: /* case [Sl,NULL], [Sl,Sr], [Sl,St] */
if n.left̸=NULL then AssignExecutor(n.left, n.executor.master)
if n.right̸=NULL then
if n.rightslave̸=NULL then
n.executor.slaves := {n.rightslave}
AssignExecutor(n.right, n.rightslave)
else n.executor.slaves := {n.rightthirdslave}
AssignExecutor(n.right, NULL)
right: /* case [Sr,NULL], [Sr,Sl], [Sr,St] */
if n.left̸=NULL then
if n.leftslave̸=NULL then
n.executor.slaves := {n.leftslave}
AssignExecutor(n.right, n.leftslave)
else n.executor.slaves := {n.leftthirdslave}
AssignExecutor(n.right, NULL)
if n.right̸=NULL then AssignExecutor(n.right, n.executor.master)
third left: /* case [St,Sr] */
n.executor.slaves := {n.rightslave}
if n.left̸=NULL then AssignExecutor(n.left, NULL)
if n.right̸=NULL then AssignExecutor(n.right, n.rightslave)
third right: /* case [St,Sl] */
n.executor.slaves := {n.leftslave}
if n.left̸=NULL then AssignExecutor(n.left, n.leftslave)
if n.right̸=NULL then AssignExecutor(n.right, NULL)
third: /* case [St,NULL], [St,SlSr] */
n.executor.slaves := {n.leftslave, n.rightslave}
if n.left̸=NULL then AssignExecutor(n.left, n.leftslave)
if n.right̸=NULL then AssignExecutor(n.right, n.rightslave)
以下是 FindThirdParty 函数的具体实现:
FINDTHIRDPARTY(n,leftmasters,rightmasters)
l := n.left; r := n.right; list := NULL
right slave view := [Jl, l.◃▹, l.σ]
left slave view := [Jr, r.◃▹, r.σ]
right master view := [l.π ∪Jr, l.◃▹∪r.◃▹∪n.parameter, l.σ ∪r.σ]
left master view := [Jl ∪r.π, l.◃▹∪r.◃▹∪n.parameter, l.σ ∪r.σ]
right full view := [l.π, l.◃▹, l.σ]
left full view := [r.π, r.◃▹, r.σ]
two slave view := [Jl∪Jr, l.◃▹∪r.◃▹∪n.parameter, l.σ ∪r.σ]
/* check if a third party can act as a slave */
if leftmasters̸=NULL then /* case [Sl,St] */
n.rightthirdslave := NULL
i := 1
while (n.rightthirdslave=NULL)∧(i< |S |) do
if Authorized(Gright slave view, Si) ∧Authorized(Gleft full view, Si) then n.rightthirdslave := Si
i := i+1
if n.rightthirdslave̸=NULL then
for each c ∈leftmasters do Add [c.server, left, c.count] to list
if rightmasters̸=NULL then /* case [Sr,St] */
n.leftthirdslave := NULL
i := 1
while (n.leftthirdslave=NULL)∧(i< |S |) do
if Authorized(Gleft slave view, Si) ∧Authorized(Gright full view, Si) then n.leftthirdslave := Si
i := i+1
if n.leftthirdslave̸=NULL then
for each c ∈rightmasters do Add [c.server, right, c.count] to list
if list̸=NULL then return(list)
/* check if a third party can act as a master */
for i:=1...|S | do
if n.leftslave̸=NULL then /* case [St,Sl] */
if Authorized(Gright master view, Si) ∧Authorized(Gleft full view, Si) then Add [Si, third right, 1] to list
else
if n.rightslave̸=NULL then /* case [St,Sr] */
if Authorized(Gleft master view, Si) ∧Authorized(Gright full view, Si) then Add [Si, third left, 1] to list
if list̸=NULL then return(list)
/* check if a third party can execute the regular join: case [St,NULL] */
for i:=1...|S | do
if Authorized(Gleft full view, Si) ∧Authorized(Gright full view, Si) then Add [Si, third, 1] to list
if list̸=NULL then return(list)
/* check if a third party can act as a coordinator: case [St,SlSr] */
c:= GetFirst(l.candidates)
while (n.leftslave=NULL)∧(c̸=NULL) do
if Authorized(Gtwo slave view, c.server) then n.leftslave := c.server
c := c.next
if n.leftslave̸=NULL then
c:= GetFirst(r.candidates)
while (n.rightslave=NULL)∧(c̸=NULL) do
if Authorized(Gtwo slave view, c.server) then n.rightslave:= c.server
c := c.next
if n.rightslave̸=NULL then
for i:=1...|S | do
if Authorized(Gleft slave view, Si) ∧Authorized(Gright slave view, Si)
∧Authorized(Gleft master view, Si) ∧Authorized(Gright master view, Si)
then Add Si to masterlist
if masterlist̸=NULL then for each m∈masterlist do Add [m, third, 1] to list
if list̸=NULL then return(list)
以下是一个算法执行示例:
| 节点 | 候选节点 | 从节点 |
| ---- | ---- | ---- |
| n7 | [SE, , 0]∗ | |
| n4 | [SE, left, 0] | |
| n8 | [SP, , 0]∗ | |
| n5 | [SP, left, 0] | |
| n2 | [SP, right, 1] | SE |
| n9 | [ST , , 0] | |
| n6 | [ST , left, 0] | |
| n3 | [ST , left, 0] | |
| n1 | [SP, left, 2] | SD |
| n0 | [SP, left, 2] | |
| 节点 | εT(n) | 对 AssignExecutor 的调用 |
|---|---|---|
| n0 | [SP, ] | (n1, SP) |
| n1 | [SP, SD] | (n2, SP) (n3, NULL) |
| n2 | [SP, SE] | (n4, SE) (n5, SP) |
| n4 | [SE, ] | (n7, SE) |
| n7 | [SE, ]∗ | |
| n5 | [SP, ] | (n8, SP) |
| n8 | [SP, ]∗ | |
| n3 | [ST , ] | (n6, ST ) |
| n6 | [ST , ] | (n9, ST ) |
| n9 | [ST , ] |
通过以上算法和示例,我们可以在安全组合权限下有效地进行分布式查询处理,确保查询计划的可行性和安全性。
3. 算法执行流程总结
为了更清晰地理解整个算法的执行过程,我们可以将其流程总结如下:
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;
A([开始]):::startend --> B(输入查询计划 T(NT,ET)、权限集 P 和模式图 G(N,e)):::process
B --> C(调用 FindCandidates 函数):::process
C --> D{是否找到候选节点}:::decision
D -- 是 --> E(调用 AssignExecutor 函数):::process
D -- 否 --> F([退出,查询计划不可行]):::startend
E --> G(返回查询计划 T 及安全分配 εT):::process
G --> H([结束]):::startend
这个流程图展示了算法的主要执行步骤:
1.
输入阶段
:接收查询计划、权限集和模式图作为输入。
2.
候选节点查找阶段
:调用 FindCandidates 函数,通过后序遍历查询树,计算每个节点的配置文件和候选节点集。如果在这个过程中没有找到任何候选节点,说明查询计划不可行,算法退出。
3.
执行器分配阶段
:如果找到了候选节点,调用 AssignExecutor 函数,通过先序遍历查询树,为每个节点分配执行器。
4.
输出阶段
:返回查询计划和安全分配。
4. 关键函数详细解析
4.1 FindCandidates 函数
该函数的主要目的是确定每个节点的安全候选集。其具体步骤如下:
1.
递归遍历子节点
:首先递归调用 FindCandidates 函数处理左子节点和右子节点。
2.
根据操作类型处理节点
:
-
投影操作(π)
:更新节点的配置文件,并将左子节点的候选集添加到当前节点的候选集中。
-
选择操作(σ)
:更新节点的配置文件,并将左子节点的候选集添加到当前节点的候选集中。
-
连接操作(◃▹)
:
- 计算各种视图,包括从节点视图、主节点视图和全量视图。
- 查找左从节点,按连接计数器递减顺序检查左子节点的候选集,直到找到第一个可以作为左从节点的候选集。
- 检查右子节点的候选集,确定它们是否可以作为半连接的主节点或常规连接的主节点,并将符合条件的候选集添加到候选列表中。
- 对称地查找右从节点和左主节点候选集,并添加到候选列表中。
- 如果没有找到候选集,调用 FindThirdParty 函数检查是否可以通过第三方介入计算该操作。
- 如果仍然没有返回任何候选集,算法退出并返回无法进行安全分配的节点。
4.2 AssignExecutor 函数
该函数的主要作用是为每个节点选择一个候选节点作为执行器。其具体步骤如下:
1.
选择候选节点
:如果有父节点推送的信息,从候选列表中搜索匹配的候选节点;否则,选择第一个候选节点。
2.
根据候选节点来源分配执行器
:
-
左子节点来源
:设置主执行器为候选节点的服务器,递归调用 AssignExecutor 函数处理左子节点和右子节点,根据右从节点的情况分配从执行器。
-
右子节点来源
:设置主执行器为候选节点的服务器,递归调用 AssignExecutor 函数处理左子节点和右子节点,根据左从节点的情况分配从执行器。
-
第三方左来源
:设置主执行器为候选节点的服务器,从执行器为右从节点,递归调用 AssignExecutor 函数处理左子节点和右子节点。
-
第三方右来源
:设置主执行器为候选节点的服务器,从执行器为左从节点,递归调用 AssignExecutor 函数处理左子节点和右子节点。
-
第三方来源
:设置主执行器为候选节点的服务器,从执行器为左从节点和右从节点,递归调用 AssignExecutor 函数处理左子节点和右子节点。
4.3 FindThirdParty 函数
该函数用于检查是否可以通过第三方介入计算连接操作。其具体步骤如下:
1.
检查第三方作为从节点的情况
:
- 对于 [Sl,St] 情况,检查是否有第三方可以作为右从节点,满足相应的权限要求。如果找到,将左主节点的候选集添加到列表中。
- 对于 [Sr,St] 情况,检查是否有第三方可以作为左从节点,满足相应的权限要求。如果找到,将右主节点的候选集添加到列表中。
2.
检查第三方作为主节点的情况
:
- 对于 [St,Sl] 情况,检查是否有第三方可以作为主节点,满足相应的权限要求。如果找到,将其添加到列表中。
- 对于 [St,Sr] 情况,检查是否有第三方可以作为主节点,满足相应的权限要求。如果找到,将其添加到列表中。
3.
检查第三方执行常规连接的情况
:检查是否有第三方可以执行常规连接,满足相应的权限要求。如果找到,将其添加到列表中。
4.
检查第三方作为协调者的情况
:
- 查找左从节点和右从节点,满足相应的权限要求。
- 如果找到左从节点和右从节点,检查是否有第三方可以作为协调者,满足相应的权限要求。如果找到,将其添加到列表中。
5.
返回结果
:如果列表不为空,返回列表;否则,返回空。
5. 总结与展望
通过上述算法和详细的解析,我们可以在安全组合权限下有效地进行分布式查询处理。算法通过优先选择半连接和选择参与更多连接操作的服务器,最小化了计算成本。同时,考虑了第三方的介入,提高了查询计划的可行性和安全性。
在实际应用中,我们可以根据具体的场景和需求,对算法进行进一步的优化和扩展。例如,可以考虑更复杂的权限模型,或者结合其他优化策略,如数据分区和缓存,以提高查询处理的性能。
希望本文能够帮助读者理解在安全组合权限下进行分布式查询处理的方法和技术,为相关领域的研究和实践提供有益的参考。
超级会员免费看
176万+

被折叠的 条评论
为什么被折叠?



