更新时间:2026-07-28 GMT+08:00
操作指导
前提条件
- 控制PACKAGE、函数和存储过程的级联失效:设置ddl_invalid_mode为invalid。
- 控制视图的级联失效:设置enable_view_invalidation为on。
- 控制支持一次性入库:设置enable_force_create_obj为on。
语法
支持通过下面的语法对存储过程、PACKAGE、视图重新编译:
- ALTER PACKAGE pkg_name COMPILE。
- ALTER FUNCTION func_name COMPILE。
- ALTER PROCEDURE proc_name COMPILE。
- ALTER VIEW view_name COMPILE。
注意事项
- PACKAGE、函数和存储过程的级联失效仅支持A兼容库。
- 除批量导入后,可能需要多次重编译使对象变为有效,其他场景不推荐在同一个环境上反复全量重建包定义,可以先删除全量包定义后再全量新建包定义。
- 全量部署完成后,建议不要连接数据库进行功能测试,重建PACKAGE和调用该PACKAGE同时进行会产生冲突。
- 功能测试前,请先检查是否存在失效对象,失效对象被调用,可能会出现一些异常情况。
- 建议避免构造对象依赖成环的场景,访问和编译会出现异常情况。
- 使用%type作为函数参数类型会被转化为对应的基础类型存储,导出过程无法识别依赖对象类型变更。
- 执行失效重编译过程中,不建议执行其它DML操作。
- 视图重编译失败时,可通过CREATE OR REPLACE VIEW语法重建视图。
操作步骤
以下步骤为整体流程步骤,具体执行代码请参见示例。
- 手动创建或者通过gs_restore等工具从外部文件向数据库批量导入对象定义。
- 通过PG_OBJECT系统表检查是否存在失效对象,失效对象的valid字段值为false。
- 执行ALTER COMPILE语法或PG_CATALOG.GS_COMPILE_SCHEMA批量重编译接口进行重编译。
- 检查PG_OBJECT系统表中是否存在valid字段是false的对象,确认全部对象变为有效。
- 正常开启业务。
示例
- 示例一:数据库对象批量导入后重编译
-- 开启失效重编译参数,全局设置DDL_INVALID_MODE='invalid',ENABLE_FORCE_CREATE_OBJ='on'。 -- 创建数据库test_database_obj_from,数据库test_database_obj_to,库test_database_obj_from用来创建对象,库test_database_obj_to用来导入对象并执行批量编译,库test_database_obj_from、test_database_obj_to都是O兼容模式库 DROP DATABASE IF EXISTS test_database_obj_from; DROP DATABASE IF EXISTS test_database_obj_to; CREATE DATABASE test_database_obj_from DBCOMPATIBILITY='A'; CREATE DATABASE test_database_obj_to DBCOMPATIBILITY='A'; -- 切换到test_database_obj_from库创建package、函数、表等对象,存在依赖关系 \c test_database_obj_from DROP USER IF EXISTS dump_plsql_user1 cascade; CREATE USER dump_plsql_user1 PASSWORD '********'; SET ROLE "dump_plsql_user1" PASSWORD '********'; DROP FUNCTION IF EXISTS dump_func1; DROP FUNCTION IF EXISTS dump_func2; DROP FUNCTION IF EXISTS dump_func3; DROP FUNCTION IF EXISTS dump_func4; DROP PACKAGE IF EXISTS dump_pkg; DROP TABLE IF EXISTS dump_tab; CREATE TABLE dump_tab(c1 number, c2 varchar(2)); INSERT INTO dump_tab SELECT generate_series(1,9), 'i'||generate_series(1,9); CREATE OR REPLACE PACKAGE dump_pkg IS CURSOR CUR IS SELECT * FROM dump_tab ORDER BY c1 DESC; FUNCTION dump_pkg_func RETURN dump_tab.c2%TYPE; END dump_pkg; / NOTICE: type reference dump_tab.c2%TYPE converted to character varying CREATE PACKAGE CREATE OR REPLACE PACKAGE BODY dump_pkg IS FUNCTION dump_pkg_func RETURN dump_tab.c2%TYPE IS v cur%rowtype; tmp dump_tab.c2%TYPE; BEGIN OPEN cur; BEGIN FETCH cur INTO v; EXCEPTION WHEN OTHERS THEN RAISE INFO 'ERROR1:%', sqlerrm; END; CLOSE cur; tmp := v.c2; RETURN v.c2; EXCEPTION WHEN OTHERS THEN RAISE INFO 'ERROR2:%', sqlerrm; RETURN 0; END; END dump_pkg; / NOTICE: type reference dump_tab.c2%TYPE converted to character varying NOTICE: type reference dump_tab.c2%TYPE converted to character varying CREATE PACKAGE BODY CREATE OR REPLACE FUNCTION dump_func1(p in varchar DEFAULT dump_pkg.dump_pkg_func()) RETURN varchar IS TYPE tp1 IS varray(5) OF int; TYPE tp2 IS varray(10) OF varchar2(100); FUNCTION sub_func(a varchar) RETURN varchar AS TYPE tp3 IS TABLE OF tp1; TYPE tp4 IS TABLE OF tp2; var1 tp4; BEGIN RETURN 'aaa'; END; BEGIN p := sub_func('aa'); RETURN p; END; / CREATE OR REPLACE FUNCTION dump_func2(p1 dump_tab.c1%TYPE default 1) RETURN dump_tab.c2%TYPE AUTHID DEFINER IS TYPE tp1 IS RECORD(a int,b number(10,3)); TYPE tp2 IS RECORD(a int,b varchar(1000)); TYPE tp3 IS TABLE OF tp1; TYPE tp4 IS TABLE OF tp2; cursor cur IS select * from dump_tab where c1 = p1; p cur%rowtype; begin FOR i IN cur LOOP if i.c1 IS NOT NULL then p := i; EXIT; END IF; END LOOP; RETURN p.c2; end; / NOTICE: type reference dump_tab.c1%TYPE converted to numeric NOTICE: type reference dump_tab.c2%TYPE converted to character varying CREATE FUNCTION CREATE OR REPLACE FUNCTION dump_func3(va in int) RETURN varchar IMMUTABLE IS subtype tp1 IS dump_tab%rowtype; TYPE tp2 IS TABLE OF tp1 index by varchar(50); v tp1; begin v.c2 := dump_pkg.dump_pkg_func(); RETURN v.c2; end; / CREATE OR REPLACE FUNCTION dump_func4(va in int) RETURN varchar SHIPPABLE IS TYPE tp1 IS RECORD(a dump_tab.c1%TYPE,b dump_tab.c2%TYPE); subtype tp2 IS tp1; v tp2; begin v.b := dump_pkg.dump_pkg_func(); RETURN v.b; end; / -- 通过dump导出对象定义 gs_dump test_database_obj_from -f a.sql -- 通过-f指令,导入定义,执行结果部分回显如下示例。 gsql -d test_database_obj_to -r -f a.sql CREATE SCHEMA ALTER SCHEMA SET gsql:a.sql:53: WARNING: depend function dump_pkg_func must be declared. DETAIL: N/A gsql:a.sql:53: WARNING: Function created with compilation errors. CREATE FUNCTION ALTER FUNCTION CREATE FUNCTION ALTER FUNCTION gsql:a.sql:95: WARNING: Relation "dump_tab" does not exist when words are parsed. CONTEXT: compilation of PL/pgSQL function "dump_func3" near line 1 gsql:a.sql:95: WARNING: "v.c2" is not a known variable. DETAIL: N/A gsql:a.sql:95: WARNING: Function created with compilation errors. CREATE FUNCTION ALTER FUNCTION CREATE TABLE ALTER TABLE CREATE FUNCTION ALTER FUNCTION CREATE PACKAGE CREATE PACKAGE BODY ALTER PACKAGE -- gsql连接后,切到test_database_obj_to库,或者gsql连接test_database_obj_to库查询是否存在失效对象 \c test_database_obj_to 或 gsql -d test_database_obj_to -r select * from pg_object where valid='f'; object_oid | object_type | creator | ctime | mtime | createcsn | changecsn | valid | relchangecsn ------------+-------------+---------+-------------------------------+-------------------------------+-----------+-----------+-------+-------------- 24619 | P | 24578 | 2026-01-08 21:36:28.040017+08 | 2026-01-08 21:36:28.040017+08 | | 1303 | f | 0 24637 | P | 24578 | 2026-01-08 21:36:28.145237+08 | 2026-01-08 21:36:28.145237+08 | | 1307 | f | 0 (2 rows) -- 可以反复执行重编译,直到所有对象都变为有效 call pg_catalog.gs_compile_schema('dump_plsql_user1',true,2); NOTICE: type reference dump_tab.c2%TYPE converted to character varying CONTEXT: SQL statement "alter package dump_plsql_user1.dump_pkg compile;" PL/pgSQL function pkg_util.gs_compile_schema(character varying,boolean,integer) line 80 at EXECUTE statement referenced column: gs_compile_schema SQL statement "select pkg_util.gs_compile_schema(:schema_name, :compile_all, :retry_times);" PL/pgSQL function gs_compile_schema(character varying,boolean,integer) line 24 at EXECUTE statement NOTICE: type reference dump_tab.c2%TYPE converted to character varying CONTEXT: SQL statement "alter package dump_plsql_user1.dump_pkg compile;" PL/pgSQL function pkg_util.gs_compile_schema(character varying,boolean,integer) line 80 at EXECUTE statement referenced column: gs_compile_schema SQL statement "select pkg_util.gs_compile_schema(:schema_name, :compile_all, :retry_times);" PL/pgSQL function gs_compile_schema(character varying,boolean,integer) line 24 at EXECUTE statement INFO: The number of executions is 1 CONTEXT: referenced column: gs_compile_schema SQL statement "select pkg_util.gs_compile_schema(:schema_name, :compile_all, :retry_times);" PL/pgSQL function gs_compile_schema(character varying,boolean,integer) line 24 at EXECUTE statement INFO: successful CONTEXT: referenced column: gs_compile_schema SQL statement "select pkg_util.gs_compile_schema(:schema_name, :compile_all, :retry_times);" PL/pgSQL function gs_compile_schema(character varying,boolean,integer) line 24 at EXECUTE statement INFO: successful gs_compile_schema ------------------- t (1 row) -- 确认没有失效对象后,执行业务。如果多次编译后仍然存在失效对象,需要单点分析,修改确认该对象依赖完整后重新编译。 select * from pg_object where valid='f'; object_oid | object_type | creator | ctime | mtime | createcsn | changecsn | valid ------------+-------------+---------+-------+-------+-----------+-----------+------- (0 rows)
- 示例二:数据库业务变更,单点对象重编译
-- 创建表,函数依赖表 CREATE TABLE tetab(a int,b int); CREATE FUNCTION tefun(param1 tetab) RETURN INTEGER AS BEGIN RETURN 1; END; / -- 变更表列信息 ALTER TABLE tetab ADD COLUMN c varchar(10); -- 查询函数有效性 SELECT pp.proname, po.valid FROM pg_catalog.pg_proc pp, pg_catalog.pg_object po WHERE pp.oid = po.object_oid AND pp.proname='tefun'; proname | valid ---------+------- tefun | f (1 row) -- 手动编译函数,再次查看对象有效性 ALTER FUNCTION tefun COMPILE; SELECT pp.proname, po.valid FROM pg_catalog.pg_proc pp, pg_catalog.pg_object po WHERE pp.oid = po.object_oid AND pp.proname='tefun'; proname | valid ---------+------- tefun | t (1 row)
- 示例三:函数、存储过程和包复杂依赖关系下的重编译
-- 创建schema、表,函数、存储过程依赖表,包依赖函数、表 DROP SCHEMA IF EXISTS tesch CASCADE; CREATE SCHEMA tesch; SET current_schema='tesch'; DROP TABLE IF EXISTS tesch.tetab1 CASCADE; DROP FUNCTION IF EXISTS tesch.tefunc1; DROP PROCEDURE IF EXISTS tesch.teproc1; DROP PACKAGE IF EXISTS tesch.tepkg1; CREATE TABLE tesch.tetab1(a int,b int); CREATE OR REPLACE FUNCTION tesch.tefunc1(param1 tesch.tetab1.a%type) RETURN INTEGER AS var1 tesch.tetab1%rowtype; BEGIN RETURN 1; END; / NOTICE: type reference tesch.tetab1.a%TYPE converted to integer CREATE OR REPLACE PROCEDURE tesch.teproc1(param1 tesch.tetab1) AS BEGIN NULL; END; / CREATE OR REPLACE PACKAGE tesch.tepkg1 AS var1 tesch.tetab1%rowtype; FUNCTION tepkg1_func(param1 tesch.tetab1.a%type DEFAULT tesch.tefunc1(1)) RETURN INTEGER; END; / NOTICE: type reference tesch.tetab1.a%TYPE converted to integer CREATE OR REPLACE PACKAGE BODY tesch.tepkg1 AS FUNCTION tepkg1_func(param1 tesch.tetab1.a%type DEFAULT tesch.tefunc1(1)) RETURN INTEGER AS BEGIN RETURN 2; END; END; / NOTICE: type reference tesch.tetab1.a%TYPE converted to integer NOTICE: type reference tesch.tetab1.a%TYPE converted to integer NOTICE: type reference tesch.tetab1.a%TYPE converted to integer NOTICE: type reference tesch.tetab1.a%TYPE converted to integer -- 变更表新增字段 ALTER TABLE tesch.tetab1 ADD COLUMN c varchar2(10); -- 查询对象有效性 SELECT pp.proname AS objname, po.valid FROM pg_catalog.pg_proc pp, pg_catalog.pg_object po WHERE pp.oid = po.object_oid AND pp.proname IN ('tefunc1', 'teproc1') UNION ALL SELECT gp.pkgname AS objname, po.valid FROM pg_catalog.gs_package gp, pg_catalog.pg_object po WHERE gp.oid = po.object_oid AND gp.pkgname='tepkg1'; objname | valid ---------+------- tefunc1 | f teproc1 | f tepkg1 | f tepkg1 | f (4 rows) -- 批量重编译 call pg_catalog.gs_compile_schema('tesch',true,10); NOTICE: type reference tesch.tetab1.a%TYPE converted to integer CONTEXT: SQL statement "alter function tesch.tefunc1 compile;" PL/pgSQL function pkg_util.gs_compile_schema(character varying,boolean,integer) line 80 at EXECUTE statement referenced column: gs_compile_schema SQL statement "select pkg_util.gs_compile_schema(:schema_name, :compile_all, :retry_times);" PL/pgSQL function gs_compile_schema(character varying,boolean,integer) line 24 at EXECUTE statement NOTICE: type reference tesch.tetab1.a%TYPE converted to integer CONTEXT: SQL statement "alter package tesch.tepkg1 compile;" PL/pgSQL function pkg_util.gs_compile_schema(character varying,boolean,integer) line 80 at EXECUTE statement referenced column: gs_compile_schema SQL statement "select pkg_util.gs_compile_schema(:schema_name, :compile_all, :retry_times);" PL/pgSQL function gs_compile_schema(character varying,boolean,integer) line 24 at EXECUTE statement NOTICE: type reference tesch.tetab1.a%TYPE converted to integer CONTEXT: SQL statement "alter package tesch.tepkg1 compile;" PL/pgSQL function pkg_util.gs_compile_schema(character varying,boolean,integer) line 80 at EXECUTE statement referenced column: gs_compile_schema SQL statement "select pkg_util.gs_compile_schema(:schema_name, :compile_all, :retry_times);" PL/pgSQL function gs_compile_schema(character varying,boolean,integer) line 24 at EXECUTE statement NOTICE: type reference tesch.tetab1.a%TYPE converted to integer CONTEXT: SQL statement "alter package tesch.tepkg1 compile;" PL/pgSQL function pkg_util.gs_compile_schema(character varying,boolean,integer) line 80 at EXECUTE statement referenced column: gs_compile_schema SQL statement "select pkg_util.gs_compile_schema(:schema_name, :compile_all, :retry_times);" PL/pgSQL function gs_compile_schema(character varying,boolean,integer) line 24 at EXECUTE statement NOTICE: type reference tesch.tetab1.a%TYPE converted to integer CONTEXT: SQL statement "alter package tesch.tepkg1 compile;" PL/pgSQL function pkg_util.gs_compile_schema(character varying,boolean,integer) line 80 at EXECUTE statement referenced column: gs_compile_schema SQL statement "select pkg_util.gs_compile_schema(:schema_name, :compile_all, :retry_times);" PL/pgSQL function gs_compile_schema(character varying,boolean,integer) line 24 at EXECUTE statement INFO: The number of executions is 1 CONTEXT: referenced column: gs_compile_schema SQL statement "select pkg_util.gs_compile_schema(:schema_name, :compile_all, :retry_times);" PL/pgSQL function gs_compile_schema(character varying,boolean,integer) line 24 at EXECUTE statement INFO: successful CONTEXT: referenced column: gs_compile_schema SQL statement "select pkg_util.gs_compile_schema(:schema_name, :compile_all, :retry_times);" PL/pgSQL function gs_compile_schema(character varying,boolean,integer) line 24 at EXECUTE statement INFO: successful gs_compile_schema ------------------- t (1 row) -- 再次查询对象有效性 SELECT pp.proname AS objname, po.valid FROM pg_catalog.pg_proc pp, pg_catalog.pg_object po WHERE pp.oid = po.object_oid AND pp.proname IN ('tefunc1', 'teproc1') UNION ALL SELECT gp.pkgname AS objname, po.valid FROM pg_catalog.gs_package gp, pg_catalog.pg_object po WHERE gp.oid = po.object_oid AND gp.pkgname='tepkg1'; objname | valid ---------+------- tefunc1 | t teproc1 | t tepkg1 | t tepkg1 | t (4 rows)
- 示例四:视图手动重编译
-- 开启视图失效重编译参数,设置ENABLE_VIEW_INVALIDATION='on'。 -- 创建表,视图依赖表。 gaussdb=# CREATE TABLE tetab_v1(a int,b int); gaussdb=# CREATE VIEW teview1 AS SELECT a, b FROM tetab_v1; -- 删除表。 gaussdb=# DROP TABLE tetab_v1; -- 查询视图有效性。 gaussdb=# SELECT c.relname, o.valid FROM pg_catalog.pg_object o JOIN pg_catalog.pg_class c ON c.oid = o.object_oid WHERE c.relname = 'teview1'; relname | valid ---------+------- teview1 | f (1 row) -- 重建视图依赖表。 gaussdb=# CREATE TABLE tetab_v1(a int,b int); -- 手动编译视图,再次查看对象有效性。 gaussdb=# ALTER VIEW teview1 COMPILE; gaussdb=# SELECT c.relname, o.valid FROM pg_catalog.pg_object o JOIN pg_catalog.pg_class c ON c.oid = o.object_oid WHERE c.relname = 'teview1'; relname | valid ---------+------- teview1 | t (1 row) -- 删除视图。 gaussdb=# DROP VIEW teview1; -- 删除表。 gaussdb=# DROP TABLE tetab_v1;
- 示例五:视图自动重编译
-- 开启视图失效重编译参数,设置ENABLE_VIEW_INVALIDATION='on'。 -- 创建表,视图依赖表。 gaussdb=# CREATE TABLE tetab_v2(a int,b int); gaussdb=# CREATE VIEW teview2 AS SELECT a, b FROM tetab_v2; -- 删除表。 gaussdb=# DROP TABLE tetab_v2; -- 查询视图有效性。 gaussdb=# SELECT c.relname, o.valid FROM pg_catalog.pg_object o JOIN pg_catalog.pg_class c ON c.oid = o.object_oid WHERE c.relname = 'teview2'; relname | valid ---------+------- teview2 | f (1 row) -- 重建视图依赖表。 gaussdb=# CREATE TABLE tetab_v2(a int,b int); -- 使用视图自动重编译,再次查看对象有效性。 gaussdb=# SELECT * FROM teview2; a | b ---+--- (0 rows) gaussdb=# SELECT c.relname, o.valid FROM pg_catalog.pg_object o JOIN pg_catalog.pg_class c ON c.oid = o.object_oid WHERE c.relname = 'teview2'; relname | valid ---------+------- teview2 | t (1 row) -- 删除视图。 gaussdb=# DROP VIEW teview2; -- 删除表。 gaussdb=# DROP TABLE tetab_v2;
- 示例六:函数、视图复杂依赖关系下的重编译
-- 开启视图失效重编译参数,设置DDL_INVALID_MODE='invalid',ENABLE_VIEW_INVALIDATION='on'。 -- 创建schema、表,函数依赖表,视图依赖函数。 gaussdb=# DROP SCHEMA IF EXISTS tesch CASCADE; gaussdb=# CREATE SCHEMA tesch; gaussdb=# SET current_schema='tesch'; gaussdb=# DROP TABLE IF EXISTS tesch.tetab1 CASCADE; gaussdb=# DROP FUNCTION IF EXISTS tesch.tefunc1; gaussdb=# DROP VIEW IF EXISTS tesch.teview1; gaussdb=# CREATE TABLE tesch.tetab1(a int,b int); gaussdb=# CREATE OR REPLACE FUNCTION tesch.tefunc1(param1 tesch.tetab1.a%type) RETURN INTEGER gaussdb=# AS gaussdb=# var1 tesch.tetab1%rowtype; gaussdb=# BEGIN gaussdb=# RETURN 1; gaussdb=# END; gaussdb=# / NOTICE: type reference tesch.tetab1.a%TYPE converted to integer CREATE FUNCTION gaussdb=# CREATE OR REPLACE VIEW tesch.teview1 AS SELECT tesch.tefunc1(10) FROM dual; -- 变更表删除字段。 gaussdb=# ALTER TABLE tesch.tetab1 DROP COLUMN a; -- 查询对象有效性。 gaussdb=# SELECT c.relname, o.valid FROM pg_catalog.pg_object o JOIN pg_catalog.pg_class c ON c.oid = o.object_oid WHERE c.relname = 'teview1'; relname | valid ---------+------- teview1 | f (1 row) gaussdb=# SELECT proname,valid FROM pg_catalog.pg_object obj JOIN pg_catalog.pg_proc proc ON obj.object_oid = proc.oid AND proname = 'tefunc1'; proname | valid ---------+------- tefunc1 | f (1 row) -- 恢复表删除字段。 gaussdb=# ALTER TABLE tesch.tetab1 ADD COLUMN a INT; -- 批量重编译。 gaussdb=# CALL pg_catalog.gs_compile_schema('tesch', true, 1); NOTICE: type reference tesch.tetab1.a%TYPE converted to integer CONTEXT: SQL statement "alter function tesch.tefunc1 compile;" PL/pgSQL function pkg_util.gs_compile_schema(character varying,boolean,integer) line 80 at EXECUTE statement referenced column: gs_compile_schema SQL statement "select pkg_util.gs_compile_schema(:schema_name, :compile_all, :retry_times);" PL/pgSQL function gs_compile_schema(character varying,boolean,integer) line 24 at EXECUTE statement INFO: The number of executions is 1 CONTEXT: referenced column: gs_compile_schema SQL statement "select pkg_util.gs_compile_schema(:schema_name, :compile_all, :retry_times);" PL/pgSQL function gs_compile_schema(character varying,boolean,integer) line 24 at EXECUTE statement INFO: failed CONTEXT: referenced column: gs_compile_schema SQL statement "select pkg_util.gs_compile_schema(:schema_name, :compile_all, :retry_times);" PL/pgSQL function gs_compile_schema(character varying,boolean,integer) line 24 at EXECUTE statement INFO: The number of executions is 1 INFO: successful gs_compile_schema ------------------- t (1 row) -- 再次查询对象有效性。 gaussdb=# SELECT c.relname, o.valid FROM pg_catalog.pg_object o JOIN pg_catalog.pg_class c ON c.oid = o.object_oid WHERE c.relname = 'teview1'; relname | valid ---------+------- teview1 | t (1 row) gaussdb=# SELECT proname,valid FROM pg_catalog.pg_object obj JOIN pg_catalog.pg_proc proc ON obj.object_oid = proc.oid AND proname = 'tefunc1'; proname | valid ---------+------- tefunc1 | t (1 row) -- 删除视图。 gaussdb=# DROP VIEW teview1; -- 删除函数。 gaussdb=# DROP FUNCTION tefunc1; -- 删除表。 gaussdb=# DROP TABLE tetab1; gaussdb=# RESET current_schema; -- 删除schema。 gaussdb=# DROP SCHEMA tesch CASCADE;
父主题: 失效重编译