GTM-Free模式简介
功能定义
GTM-Free模式下,中心事务管理节点不再参与事务处理,从而消除了GTM的单点瓶颈,提升了事务处理性能。然而,在一致性方面,该模式仅支持所有事务完成后保证读取的外部一致性,不支持分布式事务的强一致性读取,也不支持以下这种依赖查询结果的事务一致性。
INSERT INTO SELECT * FROM *;
用户场景
GTM-Free模式适用于业务对分布式事务没有强一致性要求,且用户表使用合理分布键的场景。
规格约束
GTM-Free模式下,由于采用了分布式事务最终一致的执行和并发控制机制,因此约束了部分语法的使用场景和使用方式。如果业务确有使用被限制语法的需求,那么在明确了解最终一致性行为的基础上,需要对业务进行一定程度的改造。主要涉及的约束语法和改造建议如下:
- 总体原则:所有用户表必须指定分布键(DISTRIBUTE BY),并且选择合理的分布键:
- 考虑数据分布均匀。
- 尽量选择查询中的关联条件作为分布键,保证关联查询不会引起DN节点之间的数据流动。
- 考虑将表的主键作为分布键。
- SELECT:
- 查询时,WHERE条件应包含所有分布键字段等值查询条件。
- 避免在SELECT目标列中使用子查询,可能导致计划无法下推到DN执行,影响执行性能。
- DML: 默认不支持跨节点事务,如果所执行的DML语句包含跨节点事务,会报错处理,具体分为两种场景:
- 如果用户语句在数据库内部被拆分成多条独立语句执行,会报错如下:
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;
- 如果同一个用户语句在数据库内部涉及多节点执行,会报错如下:
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条件中加上分布键等值过滤条件。
- 如果用户语句在数据库内部被拆分成多条独立语句执行,会报错如下:
- 建议开发阶段在jdbc连接串内设置application_type=perfect_sharding_type,这样所有跨节点读写操作的SQL都会报错,用来提示开发人员尽早优化语句。