
# GTM模式
为适应不同的并发和一致性要求，GaussDB提供了三种不同的GTM模式，GTM，GTM-Lite，GTM-Free。三种模式之间的主要区别是中心事务管理节点GTM的压力和事务处理流程不同，其中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模式：enable_gtm_free=off 且 gtm_option=0；
- GTM-Lite模式：enable_gtm_free=off 且 gtm_option=1;
- GTM-Free模式：enable_gtm_free=on 或 gtm_option=2。
 
GTM-lite模式和GTM模式下，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都会报错，用来提示开发人员尽早优化语句。
 
