动态加载数据
功能描述
用户在应用侧保证一张表在不同库上同时保存两份同样的数据,一个库用来执行业务操作,一个库用来作为备份。当业务数据损坏时,应用可以将备份库中对应表的相关物理文件覆盖掉业务库的对应表的物理文件,然后用动态加载的功能将业务库的表数据恢复出来,同时保证其最大字段、索引、约束等都不受影响。
语法格式
select DYNAMIC_LOAD('[schema_name.]dynamic_loading_table_name');
参数说明
DYNAMIC_LOAD函数
通过制定的表名,将覆盖到当前表上的物理文件中的数据动态加载出来,确保数据正确,同时表上的索引、约束等都保持正常
dynamic_loading_table_name
指定动态加载的表名。
注意事项
- 由于动态加载未写WAL日志,无法进行回滚恢复,建议对被加载表文件进行加载前备份,在加载后进行全量备份。
- 仅支持单机模式使用动态加载功能。
- 可针对分区中单独普通表加载。
- 不可动态加载系统表。
- 在检查前需查询文件路径,以便正确查找需要加载的表信息
- 动态加载表后,如原来在表上存在物化视图,需重建其上的物化视图。
- 执行动态加载前先进行双向检查和单向检查,以确保目标表符合动态加载条件。
双向检查
双向检查即对A,B两表的结构进行检查,需确保一致。对分区表应进行额外的检查,检查方法如下:
1、检查索引是否一致。
SELECT
indexname,
indexdef,
amname
FROM
pg_indexes
JOIN
pg_class ON pg_indexes.indexname = pg_class.relname AND pg_class.relnamespace= '模式oid'
JOIN
pg_am ON pg_class.relam = pg_am.oid
WHERE
tablename = '表名' AND schemaname= '模式名';
2、判断变量个数是否相同,两个实例的变量个数需要严格一致。
select count(*) from pg_attribute where attrelid= '表oid';
3、判断删除列是否一致,两个实例的查询结果需要严格一致。
select attname, attlen, attnum, attbyval, attalign from pg_attribute where attrelid= '表oid' and attisdropped = true;
4、判断现有列是否一致,两个实例的查询结果需要严格一致。
select attname, atttypid, attlen, attnum, attndims, atttypmod, attbyval, attstorage, attalign, attnotnull, atthasdef, attislocal, attcmprmode, attcollation, attidentity from pg_attribute where attrelid= '表oid' and attisdropped = false and attnum>0;
5、(可选)针对分区表需确认各个分区的分区策略,分区键和范围相同
select relname,partstrategy, partkey, boundaries from pg_partition where parentid = '表oid';
单向检查
单向检查是指在通过双向检查后对A,B任意单表进行限制性检查,即检查表是否符合动态加载条件。
1、判断表的索引中是否含gist索引,含有该索引则无法加载
SELECT
indexname AS index_name
FROM
pg_indexes
WHERE
tablename = '表名' AND schemaname= '模式名'
AND indexdef LIKE '% USING gist%';
2、判断表是不是列存,列存则无法加载。
SELECT
reloptions
FROM
pg_class
WHERE
relname = '表名' AND pg_class.relnamespace= '模式oid'
AND reloptions @> ARRAY['orientation=column']::text[];
3.判断表是不是压缩表,压缩表则无法加载。
SELECT
reloptions
FROM
pg_class
WHERE
relname = '表名' AND pg_class.relnamespace= '模式oid'
AND (
reloptions @> ARRAY['compression=yes']::text[]
OR
reloptions::text ILIKE '%compresstype=%'
OR
reloptions::text ILIKE '%compress_level=%'
);
4、判断表为ustore表,ustore则无法加载。
SELECT
reloptions
FROM
pg_class
WHERE
relname = '表名' AND pg_class.relnamespace= '模式oid'
AND (
reloptions @> ARRAY['storage_type=ustore']::text[]
OR
reloptions @> ARRAY['storage_type=USTORE']::text[]
);
5、判断表是否为物化视图,物化视图则无法加载。
SELECT
relname,
relkind
FROM
pg_class
WHERE
relname = '表名' AND pg_class.relnamespace= '模式oid'
AND relkind = 'm';
如果被加载的表上含物化视图,需重建物化视图。
6、判断表是否含外键约束,如表含有外键约束则无法加载。
SELECT constraint_name, constraint_type
FROM information_schema.table_constraints
WHERE table_name = '表名' AND table_schema = '模式名' AND constraint_type = 'FOREIGN KEY';
7、(可选)针对分区表,需判断表的索引中是否含分区全局索引,带分区全局索引则无法加载。
SELECT
indexname AS index_name,
indexdef AS index_definition
FROM
pg_indexes
WHERE
tablename = '表名' AND schemaname= '模式名'
AND indexdef LIKE '%GLOBAL%';
8、(可选)针对分区表,需判断表是不是interval分区,interval分区则无法加载。
SELECT
pg_partition.relname, pg_partition.parttype,pg_partition.partstrategy, pg_partition.boundaries
FROM
pg_partition join pg_class
on pg_class.oid = pg_partition.parentid AND pg_class.relnamespace= '模式oid'
WHERE
pg_partition.relname = '表名'
AND partstrategy = 'i';
示例
前提条件
操作步骤
1、在A库创建行存表并执行vacuum。
CREATE TABLE dynamic_loading_tb
(
no_w_id int ,
col BOOLEAN
);
vacuum freeze dynamic_loading_tb;
checkpoint;
2、进入B库,在B库创建行存表,并插入数据。
CREATE TABLE b_dynamic_loading_tb
(
no_w_id int ,
col BOOLEAN
);
insert into b_dynamic_loading_tb values('1','true');
insert into b_dynamic_loading_tb values('2','false');
insert into b_dynamic_loading_tb values(-2147483648,'true');
3、使用GET_RELATIVE_FILEPATHS函数查询两个表的物理文件路径及名称。
在A库执行如下命令:
select * from get_relative_filepaths('dynamic_loading_tb');
结果返回为:
relation | relation_oid | file_path | parent --------------------+--------------+-----------------------------------------------+-------- dynamic_loading_tb | 20907 | /home/vastbase/data/vastbase/base/19170/20907 | (1 row)
在B库执行如下命令:
select * from get_relative_filepaths('b_dynamic_loading_tb');
结果返回为:
relation | relation_oid | file_path | parent ----------------------+--------------+-----------------------------------------------+-------- b_dynamic_loading_tb | 20910 | /home/vastbase/data/vastbase/base/20906/20910 | (1 row)
4、模拟数据异常,将A库dynamic_loading_tb表文件”20907”备份后删除,然后将B库b_dynamic_loading_tb表文件”20910”复制到A库对应路径下并改名为”20907”。
5、在A库执行动态加载命令。
select dynamic_load('dynamic_loading_tb');
结果显示为:
dynamic_load
--------------
success
(1 row)
6、查询A库中的表的数据。
select * from dynamic_loading_tb;
结果显示为:
no_w_id | col
-------------+-----
1 | t
2 | f
-2147483648 | t
(3 rows)