C-Store: A Column-oriented DBMS(4)

来源:互联网 发布:linux命令cp 编辑:程序博客网 时间:2024/06/07 11:07
6 更新和事务
一条插入数据在WS中是如下的结构:1个列族中的1列的一个数据,加上符合排序建的数据结构。一条逻辑记录(一行记录)对应的所有插入数据都拥有相同的存储键。存储建根据更新的位置进行分配。为了防止C-store中的节点需要同步存储键,在这里每个节点都有自己的本地唯一的存储键,加上位置信息,组成全局唯一的存储键。同时,WS中的存储键要和RS中的保持一致(WS中存储键的初始值比RS中的最大值要大,所以存储键应该是递增的,无重复)。
我们在BerkeyleyDB上搭建WS。用B-tree以支持我们的数据结构。一条插入在会被添加到不同的磁盘页上,为了避免低效率,我们计划采用一个内存的缓冲池,使得字节存储的成本大大降低。这样,我们将经常用到的WS数据结构存储在内存中。
C-store的删除操作会受到锁机制的影响。实际上,C-store会期待大量的针对读数据集的即时查询,其中只穿插着少量的OLTP事务。如果C-store使用传统的锁机制,会导致大量的锁竞争,影响性能。

因此,在C-store中,我们用隔离快照(snapshot isolation)隔离了只读的事务。在保证没有不被提交的事务的前提下,隔离快照允许过去的一段时间内只有只读的事务进入数据库。这样在用隔离快照的情况下,我们则不需要进行加锁。我们称过去的这一段时间隔离快照运行在high water mark (HWM)的环境下,并介绍一个低开销的机制在多站点的环境下跟踪它的值。若是让只读事务在任意时间内都可集中运行,这样便随时都是只读事务运行的有效时间(effective time),代价很大。因此,隔离快照存在一个low water mark (LWM) 状态,这个状态在只读事务运行之前。


6.1 隔离快照(Snapshot Isolation)的提供
关键问题是,在只读事务运行的有效时间ET内,我们需要决定WS和RS的哪些数据项是可见的。因为在隔离快照的过程中,无法执行插入和删除操作。因此,ET之前的被插入的数据和ET之后被删除的数据都必须可见。为了使这个问题不消耗过多的空间资源,我们采用粗粒度的“历元(epochs)”作为单位时间戳。因此,我们为每一个WS中列族的段都保持了一个插入元组(insert tuple),其中保存着历元中每一条被插入的记录。我们用tuple mover来保证在LWM之后RS中没有插入操作,因此RS不需要这样一个插入元组。此外,对每一个列族中的每一条记录,都有一个删除元组(deleted record vector DRV)用来记录该记录是否被删除,若为删除,用0表示,因此DRV是非常稀疏的(大多数都是0),因此可采用之前说到的第二种编码方式来压缩。DRV存储在WS中,是可更新的。
为保证HWM,用timestamp authority(TA)将时间戳分为若干个历元。称从开始时间到当前时间历元的个数为epoch number。我们预计历元的时间是非常的长的。定义最初的HWM被放置在历元0上,从历元1开始执行。TA会定期的将系统移至下一个历元,它会发送一个历元完成(epoch complete)消息给每一个site,通知他们从历元e到历元e+1,这样就使得新的事务都在历元e+1上运行。每一个site都会等e历元或更早的历元中开始的事务执行完成,再给TA发送一个历元完成的消息。一旦TA收到所有的历元完成消息,那么HWM(e)执行。
【这里解释一下整个过程。隔离快照是对过去一段时间(在这里是一个历元)的事务中,只对允许这些事务中的只读事务操作数据库。在这里历元e的所有事务的操作都被记录在快照中,之前这些事务的读操作都是不对数据库进行操作的,在HWM(e)开始后,才对数据库进行操作,因此,这个过程中不用上锁】
TA进行HWM(e)操作后,所有读事务开始执行。在这里提供了一个隐射机制来让用户知道他们的查询的确切的开始时间(因为对数据库进行操作的时间是在事务提交之后)。为了不让历元数目过大而占用存储空间,这里会用一个回收(reclaim)操作。在很多数据仓库应用中,记录一般会被保持两年,因此仅将最老的历元数目记录在DRV中。


6.2 基于锁的并发控制
读写事务用严格的两阶段锁进行并发控制。在分布式数据库中,都会用到分布的锁表。我们只记录UNDO日志,没有采用严格的两阶段提交,为了避免下面描述的准备阶段(PREPARE)。
6.2.1 分布式的提交处理
在C-store中,每个事务都有一个master,用来负责分配事务的工作单元到相应的site上(一个事务会在多个site上处理),并决定事务的最终提交状态。这里不同于两阶段提交协议的地方是,没有PREPARE阶段。当master接收到事务的一个COMMIT状态时,他会一直等到所有的site上的worker提交的commit或者abort的状态。一旦一个site接收了commit消息,他会释放所有相关的锁,删除事务的UNDO日志。由于没有两阶段提交的PREPARE,有可能存在错误commit的情况,在这种情况下,发生错误的site会恢复到之前的状态,此时更新操作会用到其他site上的数据。
6.2.2 事务回滚
事务abort,逆向读取UNDO里的条目(其实操作是差不多的)。


6.3 恢复(Recovery)
像上述提到的那样,一个出现意外的site根据从其他列族的查询操作状态进行恢复。在C-store中,这还需符合K-safety。即至多K个site在恢复时间t内down机,系统还是可以保证事务的一致性的。若down机的site没有数据丢失,那么它可以从其他site直接拿更新之后的数据。我们期望在大量的只读环境中,前滚操作是方便的,因此,从常规错误中恢复是简单明确的。第二种情况是WS和RS中同时出现错误,在这种情况下,我们必须从其他的列族和链接索引中来重构,要完成这个过程,我们仅需的功能是从远端site获取辅助的数据结构(IV,DRV)。重构之后,更新必须在重构的段上再做一次。第三种情况是WS受损而RS完好,由于RS仅被Tuple Mover写入数据,所以这种情况是极少发生的。因此,我们下面将对WS中的恢复机制做讨论。
假设情况如下:考虑一个恢复site上的WS的一个列族中的一段Sr,排序建K,排序建范围R,另外还有所有包含排序键K的其他所有列族M1...Mb的集合C。tuple mover可以保证每一个WS上的段S包含在时间t(s)内所有最近插入的元组,并可以跟RS中的对应。
恢复过程中,正在恢复的site先检查C中所有包含key range K的列族,并且每一段都符合t(s)<t(sr)
SELECT desired_fields,
       insertion_epoch,
       deletion_epoch
FROM recovery_segment
WHERE insertion_epoch > tlastmove(Sr) 
      AND insertion_epoch <= HWM 
      AND deletion_epoch = 0 OR deletion_epoch >= LWM
      AND sort_key in K
只要上述查询能返回一个存储键,段中的其他field都能被相应的链接索引找到。只要存在相应的含有Sr当中key range的段,那么我们就可以在当前HWM中重构Sr。在这里考虑到一个没有cover的问题,这样的话就得花大代价来从远端获得相应的数据。为了解决这个问题,将tuple mover的操作用日志的方式记录起来,这样就可以查日志的方式得到数据。(由于暂时用不到这些内容,最后三段没有做详细翻译)
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 脚扭伤一年没好怎么办 脚扭伤半年还疼怎么办 脚崴过有后遗症怎么办 脚扭伤脚面肿了怎么办 腰突然扭了好痛怎么办 腰扭伤了怎么办最有效 腰扭伤了不能动怎么办 前交叉韧带增粗怎么办 膝盖前交叉韧带损伤怎么办 狗的腿肌肉拉伤怎么办 胳膊上的筋拉伤怎么办 肩周炎胳膊抬不起来怎么办 脖子上的筋拉伤怎么办 脚踝骨扭伤肿了怎么办 脚扭伤肿起来了怎么办 月经量特别少该怎么办 月经血沾床单上怎么办 月经弄到棉被上怎么办 血弄床单上干了怎么办 不小心吃了指甲怎么办 月经没有干净同房了怎么办 撞红了怎么办要吃药吗 自己长得太丑怎么办 长得丑特别自卑怎么办 手挤了有淤血怎么办 手指肚夹淤血了怎么办 指甲被夹了变黑怎么办 孩子手指夹肿了怎么办 指甲压了有淤血怎么办 挤到手指有淤血怎么办 指甲上有黑线是怎么办 指甲被压了要掉怎么办 脚趾肿了有脓怎么办 手指甲上的死皮怎么办 手被东西砸肿了怎么办 手被夹住有淤血怎么办 指头被车门夹了怎么办 手背夹伤了肿了怎么办 剪完指甲边肿了怎么办 手心长水泡又痒怎么办 指甲肿了有脓怎么办