在第二节讲通信协议 obmp_query 的时候,我跳过了事务控制的细节。这节讲一下事务的外部接口。
协议层对事务层提供的原始接口进行了封装,位于 sql/ob_sql_trans_control.h。这层封装为了 SQL 层调用方便,并且维护了 TransState 状态,语句执行结束时在统一的位置根据 TransState 调用正确的事务接口,保证在任何异常状态下事务资源不泄露。
而原始的事务接口位于 storage/trans/ob_trans_service.h。主要接口是三对:start/end trans,start/end stmt,start/end participant。分别对应事务,语句,语句内参与者(分区)的访问生命周期。start trans 开启事务后,返回一个 ObTransDesc 对象,它会被保存到 session 对象中,其他事务接口和后续语句执行都需要它。它是事务唯一标识,诊断问题时常用。
一般的,一个 SQL 查询或 DML 会产生三类执行计划(ObPhyPlanType):local 计划表示所有该语句执行需访问分区的 leader 都在本节点;remote 计划表示所有分区leader都在远程一个节点上;distributed 计划表示分区 leader 在多节点上的情况。开始执行前,根据语句涉及分区信息从 location cache 中获取leader位置,选择对应类别的执行计划。location cache 是一个整体架构上的重要组件,用于高效查找分区副本信息,它对外提供统一接口,屏蔽了很多分布式细节。主体实现位于 share/partition_table,sql/ob_sql_partition_location_cache.h 对它进行了封装,同时统一了虚拟表的处理。
根据语句类型(是否只读),事务类型(是否自动提交,是否弱一致性读),当前事务状态,执行计划类型等决定不同的事务控制调用。例如,本地计划自动提交,在本节点执行 start trans, start stmt, start participant, end participant, end stmt, end trans;远程计划自动提交,上述接口都在远程节点执行。对分布式计划,start/end stmt 在本节点执行,start/end participant 在每个分区 leader 所在节点上执行。这组接口设计目的是在简化事务接口与分场景优化事务性能间取得一定的平衡。
(下地铁,雨停了,未完待续~)
如果您有任何疑问,可以通过以下方式与我们进行交流:
钉钉群:33254054
github:https://github.com/oceanbase/oceanbase
博客问答:https://open.oceanbase.com/answer