数据库基础 并行与分布式数据库

1 简介

并行数据库系统:通过并行实现数据操作

分布式数据库系统:数据分布存储,每个存储地都有DBMS,数据分布和站点自治度会影响系统。主要考虑的是数据的本地所有权和增加可用度,其次才是性能。

  • 增强数据可用性:假如存储某个关系的场地崩溃了,可以继续使用别的场地的副本

  • 分布访问数据:企业的数据分布在不同的城市,可以在访问模式下的到数据存储的局部性(?)

  • 分析分布式数据:企业需要支持分析分布在不同场地的数据

2 可用结构

三种并行 DBMS硬件结构:

  • 无共享资源:每个CPU拥有自己的内存和磁盘,CPU通信通过连接网络

  • 共享内存:多个CPU通过网络通信,访问公共主存

  • 共享磁盘:每个CPU拥有自己的内存,通过网络直接访问磁盘

共享内存结构最常用,可以使用主存所以通信代价低,能获得适中的并行度,CPU数量增大会达到内存访问冲突的瓶颈

共享磁盘系统因为大量数据通过网络传输也有类似的问题

上述两个方案都会有瓶颈,增加CPU反而系统性能下降,因为冲突增加或者带宽有限。因此对于大型并行数据库系统,最优解是无共享资源的并行结构

使用无共享资源的结构,可以获得近似线性的加速

加速比 speed-up ;可扩展性 scale-up ;事务响应时间;

3 并行查询

当一个操作需要另一个操作的结果时,我们可以使用流水线并行技术;否则,我们称这两个操作是完全独立的。

如果一个操作必须得到所有的输入数据后才能输出,称为阻塞操作,对于某些阻塞操作不能用流水线

对于单个操作,将输入数据划分,并行处理每个分片,最后合并结果,称为基于数据划分的并行处理

3.1 数据划分

划分方法:

  • 轮转划分 // 假如有n个处理机,将第 i 条记录划分到 i mod n 的处理机的方法;

  • 哈希划分 // 使用特定哈希函数划分

  • 区域划分 // 对记录排序,按照排序码划分含有相同数目记录的区域

轮转划分适用于需要访问整个关系的查询,区域划分会导致数据偏斜data skew,哈希划分的数据分布比较均匀

可以使用抽样数据的分布情况来对数据进行区域划分,降低data skew,这样得到的取值区域称为划分向量

4 数据操作并行化

4.1 Bulk Load批量载入 和 Scan扫描

扫描关系时,按页并行读入,归并得到所需记录。对于选择操作也适用。

Bulk Load 也是一样的

4.2 排序

简单方法:每个CPU对本地磁盘上的记录排序,然后归并有序记录集合,并行程度收到归并阶段影响

更好的方法是:使用区域划分方法先将记录重新分布再进行排序,举个例子:如果需要对age的属性在10个处理机上进行排序,可以将age值为0-10的记录分到处理机1,age值为10-20的记录分到处理机2......然后每个处理机对记录排序,最后合并为完整的结果

4.3 连接

并行连接的基本思想就是将连接分解成k个较小的连接,对关系A和B使用相同的划分函数,使得k个小连接的并集等于A和B的连接结果,与哈希连接的划分阶段相似。

对于每个处理机,对所有的本机记录哈希划分成k个分片,存于不同的处理机上,所有处理机都是用相同的哈希函数

另一种方法,也可以将连接属性的取值范围分成k个区域,然后均匀分布在k个处理机上,容易受到数据偏斜的影响。

每一个处理机将属于i分片的记录发送到i处理机,然后每个处理机执行顺序连接,首先将输入的A和B merge,然后连接在一起。

如果使用了range partition 区域划分,那么这就是一个sort-merge 连接的并行版本;如果使用了hash 划分,那么就是hash 连接的并行版本

并行hash连接

如果A和B在分成k份后仍然很巨大,那么每个处理机上的处理效率都会很低。

我们可以用所有的处理机共同处理一个分区,首先用hash函数h1将A和B划分到k个处理机;

for i = 1, k:

用hash函数h2将第i个处理机的Ai再次划分到k个处理机;

将Ai加入in-memory hash表,对Bi同样地划分;

与in-memory的Ai进行连接

5 并行查询优化

两种方法对查询内部的操作间并行优化:

  • 将一个操作和另一个操作流水线并行,

  • 并发执行多个互不相关的数据操作

并发查询优化器不应该只考虑左深树left-deep tree,还应该考虑bushy tree 茂密树

许多优化的参数只在运行时可见,对于多用户环境,也等同于多查询的并行的情况

6 分布式数据库

特点

  • 数据的分布对用户不可见

  • 分布数据独立性,用户无需提供存储地点即可查询到所需的关系

  • 事务原子性,设计多个场地的事务同样具有原子性

6.1 分布式数据库类型

如果分布在不同场地的数据库使用相同的DBMS,称为同构分布式数据库系统

否则称为异构分布式数据库系统,多数据库系统,需要形成网关协议,用于外部应用访问的API接口。

7 分布式DBMS的体系结构

三种DBMS体系结构:客户/服务器;协同服务器 Collaborating Server;中间件 Middleware

7.1 C/S系统

一般拥有一个或多个客户进程,一个或多个服务器进程,客户进程可以向任何一个服务器进程提交查询,服务器进程负责数据管理和事务处理。

服务器是集中的,容易实现。尽可能以批量数据传输进行交互,使用客户端缓存技术。

CS结构无法处理设计多个服务器的单个查询,客户进程需要将查询分解,分别在不同的场地执行,最后再组合起来。

7.2 协同服务器

为了解决上述问题,可以使用协同服务器解决。当服务器收到需要访问其他服务器数据的查询时,将产生合适的子查询,提交给其他服务器,得到结果后组合成最终结果。

7.3 中间件系统

允许提交涉及多个服务器的单个查询,不需要数据库都具备多场地查询的能力,对于集成很难扩展的遗留系统非常有效。

事实上,只需要一个服务器有处理多个服务器查询和事务的能力即可,我们将这个协同执行多个服务器的查询的服务器称为中间件。中间件不维护数据,对来自其他服务器的数据进行操作。

8 分布式DBMS数据存储

8.1 划分

将关系划分成若干小关系或者分片,每个分片存储于不同的场地。水平划分,每个分片是原关系的数据行,垂直划分,每个分片是原关系的数据列

垂直划分必须是无损划分,也就是每一个分片都必须包含关系的唯一标志属性

8.2 Replication

指的是存储一个关系或者关系分片 的多个复件

  • 增加数据可用性:如果某个场地的系统发生故障,可以在其他场地找到需要的数据

  • 快速查询处理:使用本地数据副本加快查询速度

两种复制技术,同步复制和异步复制,差别在于是否需要将副本和原关系数据时刻保持一致

9 目录管理

我们需要保存关系进行划分以及复制的信息,记录关系是如何被分不到各个场地以及分片副本的位置,此外还需要保存用户模式,授权信息和统计信息等等

9.1 命名对象

需要对进行划分的关系命名,唯一地识别每个分片的每个副本,不能使用全局的名字,而是每个场地都能对本地对象进行命名

一般使用多个字段构成的名字来解决 ,例如本地名(同一场地的两个对象不具有相同的本地名)+产生场地名(用于标识场地)使用全局关系名和副本标识组合称为全局副本名

9.2 目录结构

在每个长度存储全局系统目录的一个副本,不会因单个场地的故障发生访问失败,对于本地目录的修改需要广播到其他的场地。

更好的做法是,在每个场地维护一个本地目录,描述该场地的所有数据副本、关系分片的副本的分布情况,以及每个副本内容的描述(垂直分片的列,水平分片的选择条件),每当有新的副本产生,或者读本在场地间移动,生成场地的目录信息需要更新

查找关系所处的场地时,需要查询生成场地的目录,目录信息可以在其他场地缓存,但是缓存的信息有可能会过时,此时应该查询关系生成场地的目录,对缓存信息进行更新

9.3 数据独立性

指的是用户提交查询时不需要考虑关系的划分和存储的复制,用户查询数据时,不需要给出数据对象的完整标志名

系统目录中的关系本地名由用户名和用户定义的关系名组合而成,用用户所在场地的标识作为关系产生场地,得到全局关系名

用户需要使用SQL命令产生全局观曦鸣的同义名,使用这个同义名引用关系,DBMS维护一个同义名synomym表,用户使用这个表得到全局关系名。全局关系名不需要修改

10 分布式查询

在分布式数据库系统中,通信代价占有很重要的部分 ,因此还要计算通信传输的页面数,以及将结果从分布的场地传输到查询场地的代价

10.1 无连接查询

考虑以下查询:

SELECT S.age
FROM Sailor S
WHERE S.rating>3 AND S.rating<7

假如对Sailor进行了水平划分,rating<5的记录存储于Shanghai,rating>5的记录存储于HongKong,那么DBMS需要在两个场地处理查询,再将结果合并起来。如果查询语句是AVG(S.age),那就需要在两个场地计算age的总和和记录的数目,再计算出sailor的平均年龄。

如果对Sailor进行了垂直划分,Shanghai存储sid和rating,HongKong存储sname和age,(该垂直划分是有损的划分,需要在关系的两个分片都增加额外的标识字段才能合并这两个分片)重构关系Sailor后,再执行查询

如果Sailor同时存储于Shanghai和HK,这就需要看传输代价和执行查询代价(如是否有可用索引)

10.2 连接操作

连接不同场地的关系的代价很高,假设Sailor存储在London,Reserve存储在Paris,下面讨论不同做法的代价

需要的时候取数据

在London做嵌套循环连接,Sailor为外关系,这种做法的代价过大,不应该使用,应该将两个关系都传到查询场地,再进行连接

不管是嵌套循环连接还是索引嵌套循环,都不是一个好方法

传输到一个场地

将关系Sailor从London传输到Paris,在Paris进行连接;或者将两个关系都传输到查询场地

半连接和布鲁连接

可以事先确定不能跟Sailor进行连接的记录,减少传输记录的数量,两种减少传输数量的技术:

  1. 半连接,分以下三步执行

    1. 在London对Sailor进行投影得到连接字段,将结果传输到Paris;

    2. 将结果与Reserves自然连接,称为Reserves基于Sailors的约减,将约减后的Reserves传输到London;

    3. 在London进行连接;

    半连接的传输代价比较小,但是总代价有可能比传输整个关系要大

  2. 布鲁连接,主要差别在于第一步传送位向量,而不是Sailor的投影。位向量长度为k,将Sailor的每条记录通过哈希函数映射到0-k-1的区域内,并将对应数位设为1。对关系进行约减时,使用同样的哈希函数,摒弃那些哈希值为在位向量对应数位为0的记录。

    这种做法的传输数量会大一些,连接代价也更大,一般增加不超过10%-20%,但是本地处理代价显著减少,因此布鲁连接在分布式连接中很流行。

10.3 基于代价的查询优化

完整的查询计划包含了若干局部查询计划,优化器产生的局部查询计划基于本地代价估计。场地能够利用本地目录的当前信息找到更好的查询计划,可以不使用建议的局部查询计划。

11 分布式数据更新

更新事务提交前,需要修改关系的所有副本,称为同步复制;异步复制被广泛使用,关系的副本只需要定期进行更新,因此同一个事务读不同的副本可能会得到不同的结果,危害数据独立性,但是更容易实现。

11.1 同步复制

两种保证事务访问某个对象的不同副本得到相同结果的技术:

  1. 投票技术

    事务在修改某个对象时写该对象的大多数副本,读的时候读足够数量的副本来确保其中之一为当前副本(每一个副本都有副本号,根据大小即可判断)例如总共有10个副本,写7个副本,那么需要读至少4个副本。

    但是一般来说读比写要频繁很多,所以重点是提高读性能。

  2. 读任意写全部技术

    事务可以读任一个副本,但是写的时候需要写所有的副本,这种方法的读速度比较快

同步复制的代价过大,更新事务前必须获得所有副本的互斥锁,向远程场地请求锁然后等待获得锁,这个过程非常耗时。如果碰到网络故障,在所有需要更新数据的场地的网络故障修复前,不能提交事务。因此实际中很少使用同步复制

11.2 异步复制

异步复制违反了分布式数据的独立性,用户需要明确自己访问的是哪个版本。

主场地和对等复制

两种异步复制的实现方法:

  1. 主场地异步复制 Primary Site

    将关系的一个副本设为主副本,在其他场地创建次副本,次副本不允许直接进行更新。主副本更新,次副本订阅。

  2. 对等异步复制 Peer-to-Peer

    多个版本都可以设计成可更新的主副本,需要传播更新,还需要使用冲突解决策略。

    对于冲突的解决方法:

    1. 不同主版本允许更新的分片不相交

    2. 同一时间只允许一个主副本进行更新

与同步复制不同的是,事务对主副本数据更新后可以立即提交,然后再进行数据传播的应用阶段。

更新数据的传播通过两步完成:

  1. 获取:系统识别出提交事务对主副本做了哪些更新

    两种实现获取的方法:

    1. 基于日志的获取,影响复制关系的日志记录会被写入CDT更新数据表,CDT中的日志有可能被清除(中止),CDT只存储提交事务的更新数据流,在获取阶段得到更新数据流,在应用阶段使用CDT中的更新数据流

    2. 基于程序的获取方法,DBMS调用程序发起获取处理,获取主副本数据的snapshot

    由于只处理更新的数据,所以基于日志的获取方法负载overhead较低,基于日志的获取需要详细了解日志的结构,日志的结构与系统直接相关 。

  2. 应用:将更新数据传播给其他副本

    可以通过主副本不停地或者周期性发送CDT或者最新快照来实现,每个次副本场地从主副本拉取数据。

  3. 数据仓库

    许多异步复制关系的集合,数据仓库的副本不常更新。适用于从多个场地获取数据的应用。

12 分布式事务

事务在某个场地提交后,该场地的事务管理器将事务分解成可在不同场地执行的多个子事务,然后将事务提交给其他场地的事务处理器。

13 分布式并发控制

以下是在场地间进行分布式加锁管理的方法:

  • 集中式:一个单独的场地负责处理所有的加锁和解锁请求

  • 主副本:制定一个副本作为主副本,所有对该数据对象的副本的加锁解锁请求,都交给主副本所在的场地锁管理器处理

  • 全分布式:对某个副本的加锁解锁请求,由该副本所在的场地锁管理器处理

集中式容易因为锁管理器的场地故障而发生问题;祝福本的方式能避免上述问题,但是数据对象的读取往往需要两个场地(读取的副本场地和主副本场地)交互,全分布式可以避免上述两个问题,但是执行写操作时需要对所有的数据副本加锁。如果读操作多,可以选择全分布式管理。

13.1 死锁

使用主副本或者全分布式进行加锁管理,需要注意死锁检测(比较通用)。每个场地维护一个本地的等待图,出现环代表出现死锁,即使不出现环,也有可能有死锁的情况。例如,两个场地A、B都有对象O1,O2的副本,事务T1先读O1,再写O2,事务T2先读O2,再写O1。出现死锁,但是在每个 场地都没有发现环。

我们因此需要使用分布式死锁检测算法,有以下三种:

  • 集中式:所有场地定期向处理全局死锁检测的场地发送本地等待图,在这个中心场地合并成全局等待图

  • 分层算法:将所有场地聚合成若干层次,例如某个省的场地形成该省的等待图,定期将省等待图聚合成国家等待图。原因是往往关系密切的场地之间更容易发生死锁。

  • Timeout:如果事务等待时长过长就将其中止,会导致不必要的事务重启,用于无法多场地共享等待图的情况。

由于传播本地信息的延迟,可能导致死锁检测出来的死锁并不存在,称为phantom deadlock,导致不必要的事务中止。

14 事务恢复

分布式DBMS的事务恢复要复杂很多,因为:

  • 故障种类增加,网络故障,事务执行故障等等

  • 一个事务的提交需要保证所有场地的子事务都提交

最广泛使用的提交协议是2PC两阶段提交协议,以及2PC的变体,具有假设中止的2PC

14.1 执行和提交事务

每个场地都进行日志维护,除了通常的日志行为以外,还需要记录提交协议的信息。事务提交场地的事务管理器称为事务协调者coordinator,子事务subtransaction执行场地称为下属subordinate

当用户决定提交事务后,提交命令传给事务协调者,2PC开启:

  1. 协调者向下属发送prepare消息;

  2. 下属得到prepare后,决定中止还是提交子事务,向日志强制写入 abort 或者 prepare,然后回复协调者 no 或者 yes;

  3. 如果协调者收到全是yes的消息,则向日志写入commit,发送commit到每个下属;

  4. 如果收到协调者收到有no消息,或者一定时间后没有收到下属的响应,向日志写入abort记录,发送abort给所有下属;

  5. 如果下属收到commit消息,向日志写入commit,发送ack消息给协调者并提交子事务;

  6. 如果下属收到abort消息,向日志写入abort,发送ack给协调者并中止子事务;

  7. 协调者收到所有的ack后,写入end记录。

14.2 恢复

恢复过程的操作:

  • 如果日志中含有commit或者abort,我们就可以重做或者取消该事务,如果该事务的场地为协调者,那么定期向下属发送commit或者abort,直到收到所有ack后写入end

  • 如果有prepare记录,而没有commit或者abort,则该事务场地是一个下属,从prepare记录中找到协调者,与协调者确定事务状态,如果协调者返回commit或者abort,则重做或者取消事务

  • 如果没有prepare、commit或者abort,证明没有投票,可以单方面决定中止或者取消

14.3 2PC优化-具有假设中止的两阶段提交

优化策略:

  • 协调者中止时,可以取消事务并且立刻删除

  • 下属收到abort后,不发送ack,协调者发送完abort后不需要等待下属应答

  • 协调者不需要在abort日志中记录下属名字

  • abort日志不需要强制写

14.4 3PC

使用3PC,协调者场地发生故障时,也能避免事务阻塞

在协调者发出prepare消息并收到yes后,发送precommit消息,收到足够数量的ack后,强制写commit。


后面的部分不太能理解,写的有点乱,等有一定的实操经验后可以再回顾一下。

你可能感兴趣的:(数据库基础 并行与分布式数据库)