云数据库 GAUSSDB-逻辑解码支持DDL:功能描述

时间:2024-11-01 17:07:49

功能描述

数据库在执行DML的时候,存储引擎会生成对应的DML日志,用于进行恢复,对这些DML日志进行解码,即可还原对应的DML语句,生成逻辑日志。而对于DDL语句,数据库并不记录DDL原语句的日志,而是记录DDL语句涉及的系统表的DML日志。DDL种类多样、语法复杂,逻辑复制要支持DDL语句,通过这些系统表的DML日志来解码原DDL语句是非常困难的。新增DDL日志记录原DDL信息,并在解码时通过DDL日志可以得到DDL原语句。

在DDL语句执行过程中,SQL引擎解析器会对原语句进行语法、词法解析,并生成解析树(不同的DDL语法会生成不同类型的解析树,解析树中包含DDL语句的全部信息)。随后,执行器通过这些信息执行对应操作,生成、修改对应元信息。

本文通过新增DDL日志的方式,来支持逻辑解码DDL,其内容由解析器结果(解析树)以及执行器结果生成,并在执行器执行完成后生成该日志。

从语法树反解析出DDL,DDL反解析能够将DDL命令转换为JSON格式的语句,并提供必要的信息在目标位置重建DDL命令。与原始DDL命令字符串相比,使用DDL反解析的好处包括:

  1. 解析出来的每个数据库对象都带有Schema,因此如果使用不同的search_path,也不会有歧义。
  2. 结构化的JSON和格式化的输出能支持异构数据库。如果用户使用的是不同的数据库版本,并且存在某些DDL语法差异,需要在应用之前解决这些差异。

反解析输出的结果是规范化后的形式,结果与用户输入等价,不保证完全相同,例如:

示例1:在函数体中没有单引号'时,函数体的分隔符$$会被解析为单引号'。

原始SQL语句:

CREATE FUNCTION func(a INT) RETURNS INT AS
$$
BEGIN
a:= a+1;
CREATE TABLE test(col1 INT);
INSERT INTO test VALUES(1);
DROP TABLE test;
RETURN a;
END;
$$
LANGUAGE plpgsql;

反解析结果:

CREATE  FUNCTION public.func ( IN a pg_catalog.int4 ) RETURNS pg_catalog.int4 LANGUAGE plpgsql VOLATILE CALLED ON NULL INPUT SECURITY INVOKER COST 100 AS '
BEGIN
a:= a+1;
CREATE TABLE test(col1 INT);
INSERT INTO test VALUES(1);
DROP TABLE test;
RETURN a;
END;
';

示例2:“CREATE MATERIALIZED VIEW v46_4 AS SELECT a, b FROM t46 ORDER BY a OFFSET 10 ROWS FETCH NEXT 3 ROWS ONLY”会被反解析为“CREATE MATERIALIZED VIEW public.v46_4 AS SELECT a, b FROM public.t46 ORDER BY a OFFSET 10 LIMIT 3”;。

示例3:“ALTER INDEX "Alter_Index_Index" REBUILD PARTITION "CA_ADDRESS_SK_index2"”会被反解析为“REINDEX INDEX public."Alter_Index_Index" PARTITION "CA_ADDRESS_SK_index2"”。

示例4:创建/修改范围分区表,START END语法格式均解码转化为LESS THAN语句:
gaussdb=# CREATE TABLE test_create_table_partition2 (c1 INT, c2 INT) 
PARTITION BY RANGE (c2) (
    PARTITION p1 START(1) END(1000) EVERY(200) ,
    PARTITION p2 END(2000),
    PARTITION p3 START(2000) END(2500),
    PARTITION p4 START(2500),
    PARTITION p5 START(3000) END(5000) EVERY(1000) 
);
support.huaweicloud.com/fg-gaussdb-cent-v8/gaussdb-48-0043.html