写点什么

一文详解 TDSQL PG 版 Oracle 兼容性实践

  • 2021 年 12 月 21 日
  • 本文字数:5922 字

    阅读完需:约 19 分钟

TDSQL PG 版分布式关系型数据库,是一款同时面向在线事务交易和 MPP 实时数据分析的高性能 HTAP 数据库系统。面对应用业务产生的不定性数据爆炸需求,不管是高并发交易还是海量实时数据分析,TDSQL PG 版都能够轻松处理。目前 TDSQL PG 版已经在金融、保险、通信、税务、政务等多个行业的核心交易系统上线运行。

# TDSQL PG 版介绍

**1. TDSQL PG 版介绍 **

自 2008 年诞生,TDSQL PG 版已有 13 年的发展历史,产品全面兼容 PostgreSQL,高度兼容 Oracle 语法,采用无共享架构,在提供大型数据仓库处理能力的同时还能完整支持分布式事务。此外,TDSQL PG 版的三权(安全、审计、管理)分立安全体系也充分满足企业对数据安全的需求。

**TDSQL PG 版具有六个方面的产品特性:**

1.访问接口丰富。支持 C/C++、jdbc/odbc、python 等各种常用语言接口。

2.扩展性良好。支持用户自定义存储过程、函数操作符。

3.MLS 安全保护能力。使用三权分立安全体系,支持数据透明脱敏加密。

4.高效 HTAP 能力。支持千万级 TPS 事务处理,全并行分布计算框架可高效完成 OLAP 计算。

5.强大数据治理能力。支持高效在线扩缩容、用户无感知数据 rebalance 和冷热数据分级存储,节省用户成本。

6.数据库特性丰富。支持各种窗口分析函数,高度兼容 Oracle 常用函数和语法。

TDSQ PG 版的应用场景满足以下业务特征,即:数据量上 OLTP 场景超过 1T 或 OLAP 场景超过 5T;并发连接数超过 2000,峰值业务 100w/s;需要在线水平扩展能力,需要兼顾 OLTP 以及 OLAP 的 HTAP 场景,还需要严格的分布式事务保证。在满足这些业务特征的情况下,TDSQL PG 版将会是合适的选择。此外,TDSQL PG 版也适用于地理信息系统、实时高并发系统以及数据库国产化等场景。

# 语法差异对比

**2. 语法差异对比**

**2.1 数据类型**

Oracle 中的许多数据类型都可以与 TDSQL PG 版相互对应。比如 Oracle 中的 number 数据类型,对应到 TDSQL PG 版里,可以用 smallint、integer、bigint、numeric(p,s)等多种数据类型进行类比替换。但受底层存储的影响,smallint、integer、bigint 的算术运算效率比 numberic 高,因此要视业务需要转换成对应的 smallint、integer、bigint,如若无法转换时才转换成 numeric(p,s)。又例如 Oracle 中的 float 对应 TDSQL PG 版中的 double precision,Oracle 中的 binary_float 对应 TDSQL-PG 中的 real,Oracle 中的 binary_double 对应 TDSQL PG 版中的 double precision 等,这些都是两者可对应的数据类型。

此外 Oracle 中也有部分特有的数据库类型如 rowid,PostgreSQL 中并没有,但 TDSQL PG 版对此做了兼容,添加了这种数据类型。又如 urowid ID 在 Oracle 中是可变长的字符存储,TDSQL PG 版中则可以用 varchar 进行替换。

long、clob、blob 等都是 PostgreSQL 中没有的数据类型。针对这些类型,TDSQL PG 版做了大量兼容。如果用户需要在应用层用 JDBC 进行连接,JDBC 驱动也需要同步进行兼容改造。Oracle 中的 date 类型也和 PostgreSQL 不同,Oracle 中可以精确到时分秒,而在 PostgreSQL 中只有年月日。为了兼容这一数据类型,TDSQL PG 版在 Oracle 兼容开关打开的情况下底层用户定义时写 Date 类型,但下方会转成 Timestamp(0),可以直接精确到秒级。(Oracle 兼容开关打开就是 Oracle 模式,不打开就是 PG 模式)。

**2.2 存储过程语法差异**

Oracle 创建存储过程的语法与 PostgreSQL 有很大差异。比如用户在 Oracle 中创建存储过程,如果不需要输入参数、输出参数,则无需括号,但在 PostgreSQL 中则必须写括号,TDSQL PG 版对此进行兼容,业务人员可根据需求选择写或不写。在函数中,Oracle 是从 is 开始,PostgreSQL 是从 as 开始,TDSQL PG 版两者都支持。PostgreSQL 中,函数存储过程 body 使用 $$进行封装,Oracle 则不需要,TDSQL PG 版两者都支持。Oracle 支持“end 存储过程名称”结束,PostgreSQL 则不支持,对此 TDSQL PG 版做了兼容。存储过程中,Oracle 使用“/”来结尾,表示该函数存储过程创建完成,但在 PostgreSQL 中则采用 language plpgsql,对此 TDSQL PG 版也做了兼容,用户可以用“/”进行结尾。

在变量声明过程中,PostgreSQL 需要指定 Declare 声明一个变量,但 Oracle 不需要,TDSQL PG 版则完全兼容。存储过程中的输入、输出参数,Oracle 支持 IN、OUT 和 INOUT 三种类型,但 PostgreSQL 不支持 OUT,TDSQL PG 版对此做了兼容,完整支持 IN、OUT 和 INOUT 三种类型。在调用方面,Oracle 存储过程的调用支持三种形式:call 后加存储过程名称、exec 后加存储过程名称、直接调用存储过程名称,而 PostgreSQL 中只能使用 call 进行调用,TDSQL PG 版对此进行兼容改造,支持三种形式。

**2.3 其他兼容性介绍**

其他兼容方面,TDSQL PG 版支持 Oracle 特有的 package 及 200 多个 Oracle 常用的系统函数。而 Hint、Merge into 语法、connect by 语法、pivot 行转列、unpivot 列转行、分区表 ddl 增强、dual 伪表、rowid、rownum、sysdate、systimestamp,这些在 Oracle 中常用的语法和函数,TDSQL PG 版都可以兼容。

此外,目前 TDSQL PG 版也支持通过 dblink 去访问 Oracle 中的数据、select 字段别名不需要 as 修饰、update 别名支持、insert all 语法同时插入多个表、特有的分页查询语法、只读事物中要获取序列等。

# 传统数据库架构瓶颈

**3. Oracle 兼容能力**

**3.1 分区表能力**

TDSQL PG 版支持 range、list 、hash 、高性能等间隔分区,并且可以实现多级分区级联,在分区表的访问方法上全面兼容 Oracle 语法,除可以直接访问子表外,还支持带父表关联子表访问。同时 TDSQL PG 版也支持 update 分区字段的值。以下图为例,0-30 范围的子表中的 id 分区键的值通过 update 将其改为 50 时,因为 50 大于 30,系统会自动将修改后的数据加入到 30-60 范围的子表,而删除 0-30 范围子表中的旧数据。TDSQL PG 版还具备分区子表合并拆分能力及新加分区时 default 分区自动移动的能力。

**3.2 分区子表合并 &拆分**

随着时间的推移,在使用过程中,系统中的分区会越来越多。为方便管理,很多用户在早期想将分区进行合并,TDSQL PG 版也像 Oracle 一样提供了分区子表合并的能力。如图中左边所示,通过 merge partitions 202001 和 202001 的分区,形成新的分区,可以有效减少分区数量,便于管理。

如果经常访问的热点数据所在分区内数据过多,就容易扫描到很多不必要的数据,这时可将分区进行拆分。如图中右边所示,将热点分区 0-60 范围分区 split 拆分,后续访问热点数据 50 时就只需扫描 30-60 范围的分区,可以有效减少数据扫描,提高查询效率。

具体的实现方式为:merge 时数据库底层会新建一个分区,将指定要合并的分区数据全面迁移,再删除旧的分区。Split 时,数据库底层会创建出新的 2 个分区,将旧分区的数据按照大于/小于拆分点进行划分,分别插入不同的新的小分区,再删除旧分区。

**3.3 Default 分区数据维护**

分区表中一般会有一个默认的 default 子分区,用于存储不属于其他子分区的数据。比如在下图中,2019 年 12 月、2020 年 3 月的数据,都不属于已有的 2020 年 1、2 月的分区,因此这些数据会自动放在 default 子分区中。如果后续用户新创建了 2020 年 3 月的分区,TDSQL PG 版可以像 oracle 一样,自动将属于 2020 年 3 月的数据从 default 子分区迁移到新分区中,在 default 子分区中就只剩 2019 年 12 月的数据。整个过程中用户完全无感知,只需要创建分区,TDSQL PG 版内部会自动进行迁移。TDSQL PG 版底层具体的实现方法:扫描 default 分区表,将满足新分区的数据插入新分区,删除 default 分区表中这些数据。

**3.4 存储过程/函数扩展语法能力**

为全面兼容 oracle,TDSQL PG 版的存储过程和函数在创建调用语法上也进行了适配,除前面提到的函数体不需要 $$包围、以/结尾、空参数不需要括号等细节外,TDSQL PG 版还支持在任意的 statement 语句、block 代码块前添加 label 标签,再 goto 跳转到指定的标签,而原生 PostgreSQL 只能在循环前加 label。实现方式是将执行指针 cur 被赋值为 label 所在位置,再从 label 所在的位置继续往下执行。

**3.5 WITH FUNCTION 语法支持**

除了储过程,TDSQL PG 版还对存储函数进行了扩展,比如在函数上添加了对 WITH FUNCTION 语法的支持。以下图为例,select 调用的 add function 函数只在此语句中有效,其他语句无效。如果系统中已经有同名函数,这个 select 语句中的 WITH FUNCTION 的优先级会高于其他同名函数。实现方式为:函数编译后不存入 pg_proc,存入 Query 的结构体中,随着 query 的清理而被清理;调查时优先查找 Query 带的 function,没有找到再查 pg_proc。

**3.6 PACKAGE**

Oracle 中 Package 比较常见,用户常用的函数大都存储在 Package 中。目前 TDSQL PG 版也支持 Package,用户可以将自定义的常用函数封装到 Package 中,使用时指定 Package 来调用对应函数。具体的实现方式是:在创建 package 时后台会创建一个对应的 schema 和里面的函数(函数内容为空),创建包体的时候指定函数内容时再去 alter function,包里的变量都放在 schema 下面,可参考 PL 实现 PL 中的变量功能。删除时则是先删除包体再删除包。

**3.7 ROWID & ROWNUM**

ROWID 和 ROWNUM 都是 Oracle 特有的语法,PostgreSQL 并不支持,TDSQL PG 版对此进行兼容改造,支持 ROWID 和 ROWNUM。

两者的区别在于:ROW ID 的兼容实现是在用户建表时,指定该表是 With ROWID。后续查询就可以查询到 ROWID 具体的值,ROWID 相当于唯一标识,在用户写入阶段会从本地 SEQUENCE 获取唯一 ID 值再加上分布式的 nodeid 进行填充,写入到用户数据文件中。ROWNUM 的实现是做完过滤和投影后 CN 返回给用户时添加的一个编号,在用户最后返回阶段进行添加。

**3.8 MERGE INTO**

Merge into 可以将两个表进行合并。以下图为例,目标是 Merge 到 Test1 中,但参考 Test2 的数据。如果能匹配上,就修改 Test1 里的数据,使数据与 Test2 的记录一致,如果不匹配,就把 Test2 的数据插入到 Test1 中。最终执行的效果类似于 Test1 合并了 Test2,将 Test2 中的数据 Merge 到 Test1 中。在实现过程中,TDSQL PG 版添加了 merge 算子,在 Query 结构体中新增了

int mergeTarget_relation;

List* mergeSourceTargetList;

List* mergeActionList; /* list of actions for MERGE (only) */

**3.9 Start with connect by**

语法解析支持 connect by 查询。在解析时通过函数 make connect by stmt 将 select stmt 改写为通过递归 CTE 查询来实现 start with connect by 层次查询子句。后续通过 TDSQL PG 版本身支持的递归 CTE 语句来执行。

**3.10 PIVOT & UNPIVOT**

Pivot 可以将行数据转列属性。语法:

PIVOT '(' target_el FOR columnref IN_P '(' pivot_expr_list ')' ')'

TDSQL PG 版实现方法是将不再 target_el 以及 columnref 中的列作为 group by 列,通过 pivot_expr_list 对 target_el 中的聚集函数参数用 case when 进行重写,规则是“有值取值、没值取空”。

UNPivot 可以将列属性转行数据, 本质是转化为 join lateral。实现方法是获取 IN 中的列,拼接成 VALUES(…),将 UNPIVOT column 和 FOR column 拼接成 VALUES 的别名,将查询中 FROM 后面的其他表与 value rte 表做 join lateral。

**3.11 其他兼容能力**

此外,TDSQL PG 版支持 Oracle 中的日期、时间、字符串、表达式等常用函数。目前 TDSQL PG 版可以兼容 98%以上的运营商、保险行业常用 Oracle 语法,兼容 85%以上的银行机构常用 Oracle 语法,有效降低传统 IT 企业的国产化及信创门槛。

# Oracle to TDSQL PG 版迁移

**4.1 迁移工程面临问题**

从 Oracle 到 TDSQL PG 版的迁移过程会涉及到四个问题:一是成本高且工作量大;二是迁移技术复杂;三是兼容程度不明确;四是迁移过程无标准化流程,突发问题频繁。我们将上述问题分门别类,逐一进行解决。

针对工作量大的问题,可以通过 TDSQL PG 版提供的简易自动化迁移平台,下发一个迁移任务即可解决;针对迁移技术复杂的问题,我们会为用户提供专业的技术支持,协助用户进行迁移;针对兼容程度不明确的问题,我们会在迁移过程中进行评估,生成评估报告来说明兼容程度;针对迁移过程无标准化流程的问题,我们会在每一步都输出相关文档、报告来进行迁移,促使流程标准化。

**4.2 迁移工具技术架构**

TDSQL PG 版迁移工具的技术架构,分为数据抽取模块和数据装载模块。数据抽取模块会从源库里面抽取,实时导出用户数据。数据装载模块会在目标库里进行实时数据写入,进行数据迁移。

针对部分语法不能完全兼容的问题,我们会进行语法转换,把数据传递到数据装载模块,数据装载模块会直接实时写入到目标库中。迁移过程中,监控模块会实时监控整个迁移任务,期间会输出兼容报告,迁移完后进行数据校验。

**4.3 兼容性评估**

兼容性评估会输出两个报告:对象兼容报告和应用兼容报告。对象兼容是指数据库的对象,如表、索引、视图、函数或数据类型等信息;应用兼容主要是指前端应用层发送给源端执行的 SQL。我们会针对这两方面输出兼容报告。

**4.4 兼容性评估报告**

对象兼容报告,分为三种颜色:蓝色代表完全兼容,不用做任何改造就可以将 Oracle 中对象在 TDSQL PG 版中进行使用;绿色代表内部转换,针对 Oracle 的使用语法或类型,工具会自动转换成 TDSQL PG 版中适配的语法和类型,从而进行迁移;红色代表不能转换,完全不兼容,需要用户人工接入。

**4.5 迁移全流程介绍**

整个迁移流程可分为四个环节。首先是应用开发适配和生产环境准备。在进行应用开发适配过程中,可以并行地进行生产环境的系统规划,调验原先的系统布局。其次是系统测试环节,将原先在 Oracle 中的存量、增量数据全部迁移过来进行测试验证,包含功能验证和性能验证。

验证完后到双轨制上线环节,相当于老系统和新系统同时并行运行。正式上线投产后,再根据用户需求判断是否需要将 TDSQL PG 版中的数据同步到老系统中。这个过程需要和用户共同完成,图中绿色部分是需要用户配合的部分,蓝色部分则是我们负责的部分。

**4.6 双轨运行方案**

下图是我们的双轨运行方案,图中有两个架构,分别是 Oracle To TDSQL PG 版和 TDSQL PG To Oracle。

业务上线前期,我们采用双轨运行,支持从 Oracle 到 TDSQL PG 版以及从 TDSQL PG 版到 Oracle 的数据同步。通过业务开关,用户可以根据需求,选择将部分业务放在原有系统或将另一部分业务放在新系统,也可以选择全部放在新系统或老系统。当双轨运行持续稳定后才会进行正式上线。双轨制运行相当于过渡环节,如果有问题,用户可以降低回退到以前的系统上,给数据增加了双层保护。当然,双轨制运行的过程相应地也会更加复杂。

TDSQL PG 版起源于技术成熟、功能强大的 PostgreSQL,在此基础上腾讯云数据库构造和发行了功能更丰富、稳定性更好、兼容性更广、安全性更高、性能更强、扩展性极好的分布式数据库 TDSQL PG 版产品。

腾讯公司对 TDSQL PG 版具有完全自主知识产权,实现安全可控, 具备在中高端市场规模化替代国外数据库的能力,在数据库基础软件层面有力支撑了国家安全可控战略发展。当前 TDSQL PG 版已经在金融、保险、通信、税务、公安、消防、政务等多个行业的核心交易系统上线运行,为众多行业客户提供优质服务。

用户头像

还未添加个人签名 2018.12.08 加入

还未添加个人简介

评论

发布
暂无评论
一文详解TDSQL PG版Oracle兼容性实践