Percolator 事务模型 你不知道的事er

---

Percolator 技术 事务

Percolator 事务隔离级别SI

Percolator提供跨表、跨行的分布式事务,隔离级别为快照隔离(snapshot-isolation)。快照隔离级别中,如果两个事务同时修改同一个行,那么事务冲突,其中一个事务必须回滚然后重试。

传统的数据库定义了 4 种隔离级别(RU、RC、RR、Serializable),但是随着技术的不断发展,上面4种已经不能完全包含所有的隔离情况,所以出现了的snapshot isolation(快照隔离)。快照隔离多采用mvcc实现,记录事务开始的时间点,将这个时间点之前的数据看作是一个快照,所有读操作都只读取该时间点之前的数据。当然本次事务中update/insert/delete的操作对本次事务也是可见的。但是该事务之后新的事务所产生的数据对本次事务是不可见的(并发场景下)。

快照隔离中读操作不涉及锁操作,所以一定程度了提高了性能。但是快照隔离引出了一个新的问题: 写偏斜(write skew),快照隔离可能会造成数据的不可串行化(non-serializable),进而导致数据的不完整性。

例如:一个银行客户有一个支票账户 X 和一个储蓄账户 Y ,当从支票账户中取款的金额超过了该账户的余额时就会自动从储蓄账户转账过来,约束条件为 X + Y >= 0 初始化值为 X = 50, Y = 50 假设事务 T1 和事务 T2 操作的顺序如下:

T1: r1(x, 50) r1(y, 50) w1(x, -20)c1

T2: r2(x, 50) r2(y, 50) w2(y, -40)c2

由例可知,T1 和 T2 为并发事务。当 T1 提交时计算 X + Y = (-20) + 50 = 30; 当 T2 提交时计算 X + Y = 50 + (-40) = 10, 因此在快照隔离条件下,两个事务都符合完整性约束条件,可以正常提交,然而提交 T1 和 T2 后的结果是 (-20)+ (-40)= -60, 违反了完整性约束条件,这种现象称为写偏斜。

2PC 提交延时扩大

导致一个 Percolator 事务提交延时很大的主要原因是:一个事务 T 在提交期间,需要再次更新它插入、更新、删除的每一行,写上提交时间戳(commit-ts)并且去除锁信息。相比 OLTP 的 DBMS 提交时间扩大,因为通常一个事务插入、更新的行可能有很多,在正常的事务 insert/update/delete 语句修改过这些行之后,还要在事务提交时刻再次修改一遍,这涉及到 buffer pool 可能要重新把这些行所在的页从外存装入内存,然后逐行获取行锁然后修改,并且这些修改仍然要记录事务日志,并且提交本地事务时候还要再次刷盘。这样,事务提交延时就会更大。对于 2PC 来说,上述这些开销一样都少不了。

写热点数据的并发性损失

由于没有事务管理器维护事务状态,当客户端宕机后,它遗留的未开始提交的事务持有的锁,以及一个事务因为写冲突而 abort 后它持有的锁,都要到事务超时后,才能被其他事务的 read 操作清除,这就增加了其他并发执行的事务发生写冲突被回滚的几率,从而降低了系统并发性,浪费了系统资源。

另外,percolator 的‘锁’(乐观锁),其实不是真正的事务锁,因为它并不能导致试图获取锁的事务阻塞等待这个锁,也不能在持有锁的事务放锁(通常是结束时)时调度等待的事务获取锁继续执行。Percolator 的锁只是一个‘被修改的标志’,一旦事务 T1 要修改一行 X 却发现它已经被 T2 锁住了,T1 就只能回滚了,无法在锁上面阻塞等待 T2 结束后再继续。

也就是说 Percolator 的读写都是用 mvcc 做并发控制的,与 PostgreSQL 相同。这带来的问题就是如果大量并发事务更新热点数据,那么系统 TPS 会很低,只能排队执行并且发生大量事务回滚。对于 Google 的 web index 数据来说,可能没有热点行,但是对于通用的 DBMS 来说,热点数据是经常会出现的。

读数据的并发性损失

Percolator 的数据行可见性判断也与传统的 MVCC 有所不同,这导致它读取数据行也可能需要等待,从而损失了并发性能。要知道 MVCC 最重要的优点就是读操作不阻塞,以确保读的性能。

传统 DBMS 的 MVCC 中,一个事务 T1 的 snapshot 记录的是它‘拍’这个快照时刻活跃事务的集合,通常以这样的方式表示:{ts-min, ts-max}, [ative-t0, active-t1... Active-tN],这里 ts-min 表示比 ts-min 小的事务全部已经提交(所以 T1 必然可以看到它们的改动), ts-max 表示比 ts-max 大的一定还没有启动(所以 T1 必然无法看到它们的改动), active-ti 数组中是活跃的事务 id 列表,这些事务的改动 T1 也是看不到的。如果一个事务 T2.id 在此快照中(即 T2.id 在数组中或者 T2.id >  ts-max),那么 T1 看不到 T2 生成的行版本,否则 T1 可以看到 T2 生成的行版本。

而 Percolator 事务模型中,按说其 MVCC 可见性判断应该是给定事务 T1,T2,当且仅当 T2.start-ts > T1.commit-ts,T2 才能看到 T1 的改动。但是从 Get() 函数的伪代码以及论文中的描述来分析判断,实际情况似乎是如果 T2.start-ts > T1.start-ts,那么 T2 就 *应该* 看到 T1 的改动。于是,当 T2 需要读取 1 行的时候发现其 lock 字段的可见的版本有锁(此时该版本必然是最新版本并且其write record 必然还没有写入 commit-ts),T2 就要等待 T1 提交后再读取。此时 T2.start-ts 与 T1.commit-ts 的大小关系哪个大都有可能。总之这样等待就会损失并发性。为什么这种情况下 T2 不去读取那个最新的已提交的行版本呢? 我认为这才是正确的做法,这样做也才能让 write record 的 commit-ts 有意义。

之所以需要在每个行提交时刻写入 commit-ts,还是因为 Percolator 事务没有全局的事务管理器,每个客户端存储着自己的事务状态。所以系统无法获知此刻有哪些活跃的事务,也就无法为事务创建快照,只能在行中写入提交时间戳,才能做 MVCC 读。

网络通信开销较大

一个 Percolator 事务执行过程中,有大量的跨节点网络通信,具体来说包括:获取两次事务 timestamp(start-ts, commit-ts),每次写入一行时与 Bigtable 系统的通信(Bigtable 本身也是一个分布式的,所以实际每写一行的网络通信很可能会更多)。事务提交时,每一行要再次写 Bigtable,通信开销翻倍。为了降低通信成本,合并了对同一行多个字段(比如写行时写入 lock 和 data 字段, 提交时清除 lock 字段和写 write record)的更新操作为单一的调用,如果没有这个优化,那么通信成本还要再次翻倍。另外,每次要读取一行时,如果 lock 字段是指向 primary row 的指针,那么还要再次读取 primary row 的 lock 字段。要 知道一个事务只有 1 个 primary row,其余写入的行都是 secondary row,也就是说大概率一旦行上面有锁,就需要再多一次网络通信(读取这行对应的 primary row 的 lock 字段)。

清理无效行的开销(GC)

Percolator 系统还需要一组 purge 后台进程,把那些被标记为删除或者过期的数据(根据行版本的commit-ts来判断)的行版本 GC 掉。由于行的所有版本都是存储在 Bigtable 系统的数据表中的,所以后台的 purge 任务也会对 Bigtable 系统构成很大的负载。这个问题是 PostgreSQL 也有的问题。Innodb没有这个问题是因为数据表上面永远只有最新版本的行,老版本的行是通过undo日志临时生成的。Innodb Undo 日志集中存放在 undo 表空间中,清理的代价要低很多。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,864评论 6 494
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,175评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,401评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,170评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,276评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,364评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,401评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,179评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,604评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,902评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,070评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,751评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,380评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,077评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,312评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,924评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,957评论 2 351