
# GTM-Free模式简介
#### 功能定义
GTM-Free模式下，中心事务管理节点不再参与事务处理，从而消除了GTM的单点瓶颈，提升了事务处理性能。然而，在一致性方面，该模式仅支持所有事务完成后保证读取的外部一致性，不支持分布式事务的强一致性读取，也不支持以下这种依赖查询结果的事务一致性。
```
INSERT INTO SELECT * FROM *;
```
#### 用户场景
GTM-Free模式适用于业务对分布式事务没有强一致性要求，且用户表使用合理分布键的场景。
#### 规格约束
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都会报错，用来提示开发人员尽早优化语句。
 
