目 录CONTENT

文章目录

【GaussDB】507内核版本新特性-视图失效重编译

DarkAthena
2026-08-09 / 0 评论 / 0 点赞 / 7 阅读 / 0 字

【GaussDB】507内核版本新特性-视图失效重编译

背景

众所周知,原生postgresql的视图如果引用了一个表,那么对这个表进行删除或者修改字段类型或者字段长度时,大概率会报错,说有视图依赖,但相同的场景在oracle并不会发生。

举个常见的场景:

业务表都在数据库A用户下,另外有个B用户权限低,申请访问A用户下的部分数据,于是A用户就把几张表授权给了B用户,然后B用户为了方便查询,创建了一个视图来关联这几张表查询,A用户并不知情。某天A用户需要对其中一张表的一个字段扩长,此时不同数据库的表现差异就来了:

  • ORACLE 中顺利执行字段长度修改
  • 原生PG中 执行字段长度修改报错

我改我的东西还要问你意见?

在这个数据库中,A地位明显高于B的地位,B用户甚至可能不跑业务,只是偶尔查下数据,于是原生PG这个设定让很多开发及运维人员感到头疼。

在GaussDB 507 版本,终于支持了视图失效重编译这个功能

官方文档

GaussDB官方文档-特性使用指导-失效重编译

注意《失效重编译》存在同名章节,一个在《参考-存储过程》里,一个在《特性使用指导》里,有部分内容重叠,各自又有多的内容。

简单测试

先看看未开启这个功能时是什么情况:

gaussdb=# show  enable_view_invalidation;
 enable_view_invalidation 
--------------------------
 off
(1 row)

gaussdb=# create table t_test_view_depend (a number(12,3),b varchar2(20));
CREATE TABLE
gaussdb=# create view v_test_view_depend as select * from t_test_view_depend;
CREATE VIEW
gaussdb=# alter table t_test_view_depend MODIFY   b varchar2(30);
ERROR:  cannot alter type of a column used by a view or rule
DETAIL:  rule _RETURN on view v_test_view_depend depends on column "b"
gaussdb=# alter table t_test_view_depend MODIFY   a number(13,4);
ERROR:  cannot alter type of a column used by a view or rule
DETAIL:  rule _RETURN on view v_test_view_depend depends on column "a"
gaussdb=# drop table  t_test_view_depend;
ERROR:  table t_test_view_depend cannot be dropped because other objects depend on it.
DETAIL:  view v_test_view_depend depends on table t_test_view_depend
HINT:  Use DROP ... CASCADE to drop the dependent objects.
gaussdb=# 

无论是删表还是改字段长度都不行。

然后打开开关,

gaussdb=# set enable_view_invalidation to on;
SET
gaussdb=# alter table t_test_view_depend MODIFY   b varchar2(30);
ALTER TABLE
gaussdb=# alter table t_test_view_depend MODIFY   a number(13,4);
ALTER TABLE
gaussdb=# select * from v_test_view_depend;
 a | b 
---+---
(0 rows)

gaussdb=# drop table t_test_view_depend;
DROP TABLE
gaussdb=# select * from v_test_view_depend;
ERROR:  View "v_test_view_depend" is invalid and please check view definition.
LINE 1: select * from v_test_view_depend;
                      ^
gaussdb=# create table t_test_view_depend (a number(12,3),b varchar2(20));
CREATE TABLE
gaussdb=# select * from v_test_view_depend;
 a | b 
---+---
(0 rows)

gaussdb=# 

可以看到打开enable_view_invalidation后,表的字段就可以被修改了,改完后查询视图也没有报错;表也可以被drop了,重建表后视图查询也不报错。

历史问题测试

顺便测一下之前我这篇文章【GaussDB】浅浅说下GaussDB中视图依赖关系的一个处理逻辑里提到的视图依赖coredump场景。

drop view if exists v_test_dep;
drop package if exists pkg_test_dep;
drop package if exists pkg_subtype;
create or replace package pkg_subtype is 
    subtype varchar_8 is varchar(8);
end;
/
create or replace package pkg_test_dep is
    function func(i int) return pkg_subtype.varchar_8;
end;
/
create or replace package body pkg_test_dep is
    function func(i int) return pkg_subtype.varchar_8 is
    begin
        return i::text;
    end;
end;
/
create or replace view v_test_dep as
    select 1 from dual where pkg_test_dep.func('1')='1';

create or replace package pkg_subtype is 
    subtype varchar_8 is int;
end;
/

select * from v_test_dep;

先测没打开视图依赖的表现:

gaussdb=# select * from v_test_dep;
ERROR:  The function 57554 header changes during execution.
DETAIL:  N/A
gaussdb=# select * from v_test_dep;
Connection has been closed by peer, remote ip:(null), port:5432.
The connection to the server was lost. Attempting reset: Failed.
!> 

和506版本有所变化,之前是查询视图就coredump,到507版本后,第一次查询报错,第二次才触发coredump

然后测打开视图依赖的表现,这里又要分两种情况:

  • 在修改了视图依赖对象后,查询视图之前打开开关,还是会coredump
gaussdb=# create or replace package pkg_subtype is 
gaussdb$#     subtype varchar_8 is int;
gaussdb$# end;
gaussdb$# /
gaussdb=# set enable_view_invalidation to on;
SET
gaussdb=# select * from v_test_dep;
Connection has been closed by peer, remote ip:(null), port:5432.
The connection to the server was lost. Attempting reset: Failed.
!> 
  • 在修改视图依赖之前打开开关,不coredump了,视图直接变为可查询。
gaussdb=# set enable_view_invalidation to on;
SET
gaussdb=# create or replace package pkg_subtype is 
gaussdb$#     subtype varchar_8 is int;
gaussdb$# end;
gaussdb$# /
CREATE PACKAGE
gaussdb=# select * from v_test_dep;
 ?column? 
----------
        1
(1 row)

也就是说华为引入的这个视图失效重编译特性,意外解决了这个coredump问题。

为什么说是意外,因为如果他们知道这个coredump场景,就不会只在打开这个参数时才不coredump,数据库默认是关闭了这个参数的。

乱序创建场景

以上是失效重编译,对应的场景是按顺序正常创建对象后再去修改视图依赖的对象;其实还有另一个场景,就是不按顺序创建,比如先建视图,再建视图里的表,这个场景在GaussDB 507版本中也得到了支持,不过是另一个参数 enable_force_create_obj ,这个参数在之前版本只覆盖pl对象,即 package/procedure/function ,而在507版本中,新增了对 view 的覆盖。

从文档也可以看到变化:

  • 506:

参数说明:用于控制一次性入库功能的开启与关闭。开启该参数后,若创建或重建函数、包时存在未定义的对象,会创建一个虚拟的对象用于编译,并在函数体编译的过程中通过try catch捕获异常,使创建或重建过程能够运行成功。多租场景下,该参数可在PDB级别设置。

  • 507:

参数说明:用于控制一次性入库功能的开启与关闭。开启该参数后,若创建或重建函数、包时存在未定义的对象,会创建一个虚拟的对象用于编译,并在函数体编译的过程中通过try catch捕获异常,使创建或重建过程能够运行成功; 创建视图时,如果视图依赖的对象不存在或缺少查询权限,该视图仍能够创建成功。 多租场景下,该参数可在PDB级别设置。

这个参数就不进行测试演示了,文档已经说清楚了效果。如果展开具体场景,细节会非常多,对本文而言有点喧宾夺主了。不过需要注意的是,这个参数也是默认关闭的,但对于存储过程依赖多的,建议还是打开。

元数据

  • pg_depend
    原生PG对于视图内对象的依赖关系管理,在GaussDB中还是保留的,即pg_depend,这个不再多言,可以自行查找相关材料,或者看我以前写的这篇文章《从pg_depend和pg_class开始了解MogDB/openGauss/postgresql的系统元数据设计》

  • pg_object
    视图的生效失效状态记录在pg_object.valid,但要注意,这个状态为false时并不代表视图就无法查询,这个处理逻辑和ORACLE是类似的:

当修改视图内引用的对象时,视图变为无效,下次查询视图时自动重新编译,编译通过则变为有效,并返回查询结果;或者手动编译为有效后再查询。不过什么样的修改会导致视图变为无效,GaussDB和ORACLE不完全一样,这个我也懒得展开说了。

  • gs_dep_source
    gs_dep_source里面对于每个视图,会有一条object_typev的记录,里面的source会记录展开后的完整SQL,包括schema和select *的字段,操作符也会变成operator的语法,自动类型转换也会显示出来。比如本文中的两个例子。
CREATE OR REPLACE VIEW public.v_test_dep("?column?") AS SELECT 1 AS "?column?" FROM pg_catalog.dual WHERE ((public.pkg_test_dep.func(1))::text OPERATOR(pg_catalog.=) '1');
CREATE OR REPLACE VIEW admin.v_test_view_depend(a, b) AS SELECT t_test_view_depend.a, t_test_view_depend.b FROM admin.t_test_view_depend;
  • pg_rewrite
    pg_rewrite.ev_action_def里会记录视图的查询语句部分,但这里面的东西并不保持稳定不变:
  1. 这里在正常创建视图,且未做任何修改操作时,记录的是创建视图的 "真原始SQL:
select * from t_test_view_depend
  1. 在经历过视图失效重编译成生效后,会变成和gs_dep_source.source里记录的查询SQL部分一样,比如
SELECT t_test_view_depend.a, t_test_view_depend.b FROM admin.t_test_view_depend

内置函数变化

  • 引入了一个新内置函数 transform_view_dep_source()

描述:刷新GS_DEP_SOURCE系统表的source字段。即将视图定义语句中SELECT *的星号扩展;将视图创建时对象使用的schema补充写入;刷新视图依赖关系。该函数仅支持管理员用户调用。
参数:无
返回值类型:void

个人猜测这个是在从低版本升级到507时自动执行的,因为低版本的gs_dep_source之前记录的是原始SQL,而不是展开后的SQL。然后我去507的升级脚本里搜了一下,果然搜到了

"upgrade_catalog_otherdb\upgrade-post_catalog_otherdb_98_145.sql"

SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 8401;
CREATE OR REPLACE FUNCTION pg_catalog.transform_view_dep_source()
RETURNS void
LANGUAGE internal
AS $function$transform_view_dep_source$function$;

SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 0;

SELECT pg_catalog.transform_view_dep_source();

也就是说实际上在507使用过程中,这个函数一般是用不上的。

  • 修改了一个原有内置函数 gs_compile_schema(schema_name in varchar2 default null, compile_all in boolean default false, retry_times in int default 10)

原本只支持对PL对象的编译,现在新增了对视图的编译。

总结

GaussDB 507引入的这个视图无效重编译特性是非常有必要的,无论是从ORACLE迁移还是新开发系统,视图不应该阻碍对表定义的修改。我大概测试下来,各项行为基本符合预期,不过我也没去做更复杂的测试。但个人认为,这个参数还是先打开再去跑PoC业务验证更好,有问题也能尽早报给华为去修复。

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin
博主关闭了所有页面的评论