真实数据写入或产生流程

有以下几个问题请教?
1、 ob写入的增删改数据 是以什么形式写入observer,kv直接写入到memtable?
2、从上2个截图中看,ob的数据复制是以redo log为基础,所谓的2PC是异步提交方式,貌似并不是实时的把log通过paxos确认多数写入,假如一个事务没超过2M,然后提交时才同步redolog,Leader收到commit确认后挂了,其他成员还未完全写完日志未完成commit,此时该如何处理?

我先回答你第一个问题, 晚一点回答第二个问题

你这个问题回答比较长, 而且详细介绍差不多一篇万字文章, 先简单的说, 不是kv 简单直接写进入memtable, 详细介绍, 推荐学习一下 OceanBase 社区 这个里面第6个视频和第9个视频, 专门介绍 《oceanbase 存储引擎的》

1 个赞

第二个问题,2PC中每个持久化日志的过程都是paxos形成多数派后才会应答。如果一个参与者发出commit确认时,这个参与者的日志一定是形成多数派了。
只要所有参与者的prepare日志都形成多数派了,那说明所有参与者的prepare阶段都完成了,此时就可以应答客户端事务完成。如果协调者挂了,可以从参与者中重新选出一个协调者把事务时推进成功。

感谢! 视频之前也看过 主要还是说的是物理存储结构 ,类比tidb,tidb是写时先在tidb server 然后commit时写到tikv。对于ob来说 除去格式转换的过程,如果不是直接写入memtable的话 是写在哪里,有没有什么方式控制写入区域大大小,写入区域达到什么量级会写入memtable? 另外在读时 block cache/row cache只是块或行级别的缓存数据,对于有join 聚合时 这些数据在哪里处理? 另,期待万字长文。

感谢! 找了些官方说明 关于2PC的,貌似没有地方明确说明Prepare阶段会把日志形成多数派确认。也可能我没找到, 上面截图里说的Prepare log,听起来更像是另一种形式的日志,名词而非动词。


另外prepare阶段完成日志多数派就返回commit成功那么此时leader切换了原来的副本还没apply完成怎么办

我们就是写到memtable, memtable 大小由参数memstore_limit_percentage决定,表示租户的 MemStore 部分占租户总内存的百分比.

当内存达到一定程度时, 会将memtable中的数据dump到磁盘上(L1的mini sstable), 当MemStore内存使用超过freeze_trigger_percentage定义的百分比时(默认50%),触发冻结及后续的转储/合并等行为

1、也就说说 对于ob来说 写入操作 不管是kv也好还是转换后的其他格式也好,客户端的写请求是直接写入到memtable,没有额外的内存 或缓存等先临时存储写入信息?

2、 看上图2阶段提交过程中,在Prepare阶段 follower收到日志后完成多数派返回后,客户端数据是直接写入memtable,也就说leader上只有真实数据写入 和 log 发送确认过程,不是通过log 回放产生的真实数据写到存储引擎。

3、对于join、聚合、排序等是在需要哪个内存区域完成? sql_work_area的作用是什么? 从名字上看像oralce中PGA的workarea
image

以下是三个问题的回答,希望能解决你的疑惑。

  1. 是的,数据会直接写入到memtable,不需要额外的缓存。memtable本质上就是一种缓存。

  2. 两阶段提交(2PC)中的协调者和参与者,与paxos协议中的leader和follower是两个概念。paxos协议保存数据的多个副本,如果一个副本丢失了,其他大多数副本还能正常提供服务。两阶段提交是为了保证事务的一致性,一个参与者可以理解为一个数据分区(这个分区对应一组paxos多副本),一个事务涉及到多个分区,就有多个参与者,只有所有参与者全部prepare之后,才能进行commit。paxos只要多数派成立就行,因为它们保存了同一份数据的多个副本,2PC需要所有参与者返回prepare ok,因为它们每一个都对应了不同的数据,缺一不可,这是事务的原子性要求。
    再回到这个问题本身,OceanBase 的两阶段提交在传统两阶段基础上做了优化,协调者不需要写prepare log和commit log,它是无状态的,这样做减少了2次IO的开销。 两阶段提交只是为了提交事务,涉及到的log都不包含用户的数据,数据在commit之前就写入了。在paxos同步过程中,leader当然是要写数据日志的,OceanBase 中叫clog,也就是常说的undo/redo log。

  3. ob_sql_work_area_percentage 用于控制 SQL working area 的内存大小,一般的 join,sort 使用的就是 SQL working area 的内存。

感谢,继续请教
1.memtable再写到一定阈值后flush,如果写了一个比较大的事务,memtable已经写了多次了,最终大事务失败回滚,再回滚时应该也只是写个相同key的DELETE信息吧? 是否需要读取前面已经flush到磁盘的数据才能确定哪些需要回滚?
2. 单机多分区事务也是分布式事务,官方描述会优化为1pc, 这个过程是什么样的?官方的画的2pc 流程感觉更像是一种异步提交过程

  1. workarea内存不够后如何处理?
  1. 写入一条delete的方式是可行的,但是对于多行插入的事务来说代价太大了。OceanBase采取的方式是将事务状态标记为回滚(事务状态也是要持久化的),之后在读取该行数据时,发现对应事务是未提交的,就去检查事务状态表,如果事务已经回滚,那么这条记录就是无效的。如果回滚的是insert操作,说明这行数据不存在,就可以直接返回;如果回滚的是update记录,说明还有更早的insert记录,需要继续查找该行数据。
    回滚是不需要检查磁盘状态的,不管数据是否更新到了磁盘,只要将事务状态标记为回滚即可。
  2. 1PC优化存在一些问题,现在最新的版本是不建议使用的,可以不用考虑。
    2PC流程有点像异步,参与者全部prepare之后,先给上层返回提交成功,再给参与者发送commit请求。如果发送commit req时协调者宕机,恢复之后参与者可以根据prepare log继续推进两阶段提交流程。
  3. SQL working area 空间不够的话,部分数据就会落盘,继续执行jion等操作(类似于用磁盘空间作为虚拟内存的方式)。如果因为某些原因落盘失败,操作无法继续进行下去,那么这条sql语句就会报错。

感谢,我的问题比较多,再追问几个

  1. 目前在官方文档看到 ,有内存事务表,里面有版本 事务id等,log里也有记录事务,您说的事务状态持久话指的内存事务表会定期或某种机制持久化到某些地方吗?

2、OB中row key的具体组成或格式是什么样?比如key中包含 事务ID、版本信息、锁结构? 如何通过key信息区分不同的表 分区 索引? 另外按下面描述锁存储在行数,当行数数据从memtable flush后 然后提交 锁该如何清理?


3、 不使用 1PC时 ,对于 partition group的单机多分区事务来说,从2PC流程、RPC、IO上来讲和多机多分区没有区别吧(看redo log 只区分本地单分区和分布式2种)? 如果是一样的话单机多分区事务有没有其他的额外优化?
在涉及多机多分区事务时,是不是每个observer中同一个事务在每个都有一条记录?不同server的记录 使用自己的local version,在提交后更新为相同的global version?