22、安全组合权限下的分布式查询处理:第三方参与与安全查询计划构建

安全组合权限下的分布式查询处理:第三方参与与安全查询计划构建

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. 总结与展望

通过上述算法和详细的解析,我们可以在安全组合权限下有效地进行分布式查询处理。算法通过优先选择半连接和选择参与更多连接操作的服务器,最小化了计算成本。同时,考虑了第三方的介入,提高了查询计划的可行性和安全性。

在实际应用中,我们可以根据具体的场景和需求,对算法进行进一步的优化和扩展。例如,可以考虑更复杂的权限模型,或者结合其他优化策略,如数据分区和缓存,以提高查询处理的性能。

希望本文能够帮助读者理解在安全组合权限下进行分布式查询处理的方法和技术,为相关领域的研究和实践提供有益的参考。

【电动汽车充电站有序充电调度的分散式优化】基于蒙特卡诺和拉格朗日的电动汽车优化调度(分时电价调度)(Matlab代码实现)内容概要:本文介绍了基于蒙特卡洛和拉格朗日方法的电动汽车充电站有序充电调度优化方案,重点在于采用分散式优化策略应对分时电价机制下的充电需求管理。通过构建数学模型,结合不确定性因素如用户充电行为和电网负荷波动,利用蒙特卡洛模拟生成大量场景,并运用拉格朗日松弛法对复杂问题进行分解求解,从而实现全局最优或近似最优的充电调度计划。该方法有效降低了电网峰值负荷压力,提升了充电站运营效率经济效益,同时兼顾用户充电便利性。 适合人群:具备一定电力系统、优化算法和Matlab编程基础的高校研究生、科研人员及从事智能电网、电动汽车相关领域的工程技术人员。 使用场景及目标:①应用于电动汽车充电站的日常运营管理,优化充电负荷分布;②服务于城市智能交通系统规划,提升电网交通系统的协同水平;③作为学术研究案例,用于验证分散式优化算法在复杂能源系统中的有效性。 阅读建议:建议读者结合Matlab代码实现部分,深入理解蒙特卡洛模拟拉格朗日松弛法的具体实施步骤,重点关注场景生成、约束处理迭代收敛过程,以便在实际项目中灵活应用改进。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值