每个实体组实际上就像一个小的数据库,在实体组内部提供了完整的序列化ACID语义(Serializable ACID Semantics)支持。
Megastore提供了三种方式的读分别是current、snapshot和。其中current读和snapshot读总是在单个实体组中完成的。在开始某次current读之前,需要确保所有已提交的写操作已经全部生效,然后应用程序再从最后一个成功提交的失误时间戳位置读取数据。对于snapshot读,系统取出已知的最后一个完整提交的事务的时间戳,接着从这个位置读数据。和current读不同的是,snapshot读的时候可能还有部分事务提交了但未生效。inconsistent读忽略日志的状态直接读取最新的值。这对于那些要求低延迟并能容忍数据过期或不完整的读操作是非常有用的。
Megastore事务中的写操作采用了预写式日志(Write-ahead Log),也就是说只有当所有的操作都在日志中记录下后写操作才会对数据执行修改。一个写事务总是开始于一个current读以便确认下一个可用的日志位置。提交操作将数据变更聚集到日志,接着分配一个比之前任意一个都髙的时间戳,然后使用Paxos将数据变更加入到日志中。这个协议使用了乐观并发(OptimisticConcurrency):尽管可能有多个写操作同时试图写同一个日志位置,但只会有1个成功。所有失败的写都会观察到成功的写操作,然后中止并重试它们的操作。
一个完整的事务周期要经过如下几个阶段。
(1)读:获取最后一次提交的事务的时间戳和日恚位置。
(2)应用逻辑:从Bigtable读取并且聚集数据到日志入口。
(3)提交:使用Paxos达到一致,将这个入口追加到日志。
(4)生效:将数据更新到Bigtable中的实体和索引。
(5)清除:清理不再需要的数据。
Megastore中事务间的消息传递是通过队列、(Queue)实现的,图2-23显示了这一过程。

Megastore中的消息能够横跨实体组,在一个事务中分批执行多个更新或者延缓作业(Defer Work)。在单个实体组上执行的事务除了更新它自己的实体外,还能够发送或收到多个信息。每个消息都有一个发送和接收的实体组:如果这两个实体组是不同的,那么传输将会是异步的。虽然这种消息队列机制在关系型数据库中已经有了很长的应用历史,Megastore实现的这种消息机制的最大特点在于其规模:声明一个队列后可以在其他所有的实体组上创建一个收件箱。
除了队列机制之外,Megastore还支持两阶段提交(Two-phase Commit)。但是这会产生比较高的延迟并且增加了竞争的风险,一般情况下不鼓励使用。