一、背景
在异构数据库迁移到postgres的过程中,会遇到困难主要集中在:
1、旧数据迁移
2、旧应用系统的平滑过渡。
而数据迁移和应用迁移过程中,集中体现在数据库兼容性方面。虽然postgres支持目前主流数据库的大部分数据类型及相关特性,但是在SQL语法上和主流的商业数据库存在一定的差异,造成迁移数据和应用系统时,改造量过大,迁移成本较高,同时难以保证稳定性。
本文主要分析postgres的查询执行过程,提供拓展语法特性的相关思路,降低异构数据库迁移到postgres的成本。
二、兼容性extension设计
1.查询执行过程
分析postgres的查询执行过程,相关分析过程在之前的文章中已经有所体现,具体可以看
PostgreSQL查询语句执行过程
PostgreSQL查询SQL的语法分析(1)——词法分析
查询执行过程
当postgresql的后台服务进程postgres收到前台发来的查询语句后,首先将其传递到查询分析模块,进行词法分析,语法分析和语义分析。若是功能性命令(例如create table,create user和backup命令等)则将其分配到功能性命令处理模块;
对于查询处理命令(SELECT/INSERT/DELETE/UPDATE)则为其构建查询语法树,交给查询重写模块。
查询重写模块对其进行语义分析,生成查询树,交给执行计划模块。
执行计划模块对查询进行查询评估和优化,生成查询执行计划,交给查询执行模块。
查询执行模块根据查询执行计划执行查询。
总的来说流程如下:
SQL命令 --(词法和语法分析)--> 分析树 --(语义分析)--> 查询树 --(生成查询计划)--> 查询计划 --(执行查询计划)-->返回查询结果
在代码里的调用路径如下(方框内为函数,数字显示了调用顺序):
语义分析过程:
2.兼容性extension设计
根据查询执行过程分析可以看出,SQL进入查询流程时,首先对其进行词法和语法分析,不符合语法规则的SQL,直接报错,不会再执行到后面的流程中,所有,如果要做语法性兼容,首先要在语法分析模块之前,对其进行兼容性改造。改造方案有两个:
方案1
改造思路:在词法分析函数pg_parse_query()中,把调用语法分析raw_parse函数改为if else分支,增加hook指针判断。
方案2
改造思路:在词法分析函数pg_parse_query()中,把调用语法分析raw_parse函数前加入hook指针判断,如果存在,则调用改写SQL语句。
方案对比
方案1:实现了一个完整的语法分析,同时兼容postgres和oracle(或其他数据库),改造基于postgres的语法分析器实现。
方案2:实现了一个差异化的语法分析,区别postgres和oracle(或其他数据库)语法不同点,分析后需要改写原来的SQL语句。
四、注意问题
此extension的语法兼容性改造,只适合作为语法兼容,不适合做语义兼容。
例如一个无参函数:
/* 语句1:标准的SQL写法*/
select func() from t;
/* 语句2:oracle 支持省去无参函数后面的括号 */
select func from t;
对于语句1,语法分析过程可以将func判断为函数。
对于语句2,语法分析过程中,无法知道func属于语法、函数或者其他对象,只有在语义分析过程,通过查阅数据库字典表对象,才能区分。