更新时间:2023-10-17 GMT+08:00
分享

GTM模式

为适应不同的并发和一致性要求,GaussDB提供了两种不同的GTM模式,GTM-Lite,GTM-Free。两种模式之间的主要区别是中心事务管理节点GTM的压力和事务处理流程不同,其中GTM-Lite模式下,中心事务处理节点的压力得到减轻,事务处理流程进一步优化,GTM的性能和并发瓶颈得到减轻,在保证一致性的情况下,事务处理能力得到更大限度的提升;在GTM-Free模式下,中心事务管理节点不再参与事务管理,消除了GTM单点瓶颈,可达到更高的事务处理性能,但是在一致性方面,支持所有事务运行完,保证读的外部一致性,不支持分布式事务强一致性读,不支持insert into select * from等依赖于查询结果的事务一致性。

当前版本暂不支持两种模式之间的相互切换,建议使用安装时默认的GTM模式,支持升级前后GTM模式不变化。

相关的GUC参数包括enable_gtm_free和gtm_option,可通过gsql执行show语句查询当前GTM模式:

SHOW enable_gtm_free;
SHOW gtm_option;
具体模式判断方法如下。
  • GTM-Lite模式:enable_gtm_free=off 且 gtm_option=1;
  • GTM-Free模式:enable_gtm_free=on 或 gtm_option=2。
GTM-lite模式下,GaussDB支持分布式事务强一致和完整的语法功能。GTM-FREE模式下,由于采用了分布式事务最终一致的执行和并发控制机制,因此约束了部分语法的使用场景和使用方式。如果业务确有使用被限制语法的需求,那么在明确了解最终一致性行为的基础之上,需要对业务进行一定程度的改造。主要涉及的约束语法和改造建议如下:
  1. 总体原则:所有用户表必须指定分布键(DISTRIBUTE BY),且选择合理:
    • 考虑数据分布均匀。
    • 尽量选择查询中的关联条件作为分布键,保证关联查询不会引起DN节点之间的数据流动。
    • 考虑将表的主键作为分布键。
  2. SELECT:
    • 表查询时,WHERE条件应包含所有分布键字段等值查询条件。
    • 避免在SELECT目标列中使用子查询,可能导致计划无法下推到DN执行,影响执行性能。
  3. DML:
    默认不支持跨节点事务,如果所执行的DML语句包含跨节点事务,会报错处理,具体分为两种场景:
    1. 如果用户语句在数据库内部被拆分成多条独立语句执行,会报错:INSERT/UPDATE/DELETE/MERGE contains multiple remote queries under GTM-free mode Unsupport DML two phase commit under gtm free mode. modify your SQL to generate light-proxy or fast-query-shipping plan。这时,需要修改语句,来单节点执行。

      举例:

      insert into t select * from b where b.c = xx;

      假设t表和b表的分布键不同,且上述where条件只会过滤出一条数据。在不打开enable_stream_operator的情况下, 上面的查询在数据内部会被拆分成两条独立语句串行执行:首先执行select * from b where b.c = xx从某个DN节点抽取到目标记录;然后再执行insert into t语句,将抽取的目标记录下发到另一个节点DN节点完成插入。在gtm-free模式下,这样的语句执行方式会返回上述报错。类似的,create table as select * from、带子查询的delete/join/insert等语句,也可能会出现类似报错。

      业务改造方案:在业务执行之前,需要加上set enable_stream_operator=on命令,打开流算子,使得业务语句可以被整体下推执行。

    2. 如果同一个用户语句在数据库内部涉及多节点执行,会报错:Your SQL needs more than one datanode to be involved in。这时,建议对语句进行修改,使得能够单节点执行。

      举例:

      insert into t values(3,3),(1,1);

      假设(3,3)和(1,1)被分布在不同的DN节点上,那么上述语句在数据库内部的执行过程会涉及两个DN节点。在gtm-free模式下,这样的语句执行方式会返回上述报错。

      业务改造方式:对于上述语句,如果业务确有需要在多个节点上执行,需要在语句中添加一个hint来避免报错,如下:

      insert /*+ multinode */ into t values(3,3),(1,1);

      类似的,对delete和update语句也有类似约束,一般建议用户在delete和update语句的where条件中加上分布键等值过滤条件。

  4. 建议开发阶段在jdbc连接串内设置application_type=perfect_sharding_type,这样所有跨节点读写操作的SQL都会报错,用来提示开发人员尽早优化语句。

相关文档