一、数据迁移
数据迁移当前解决方案依赖dbeaver表右键导出数据的方式执行。参考如下:

二、更新序列
开发提供以下脚本用于更新所有使用序列(nextval 作为默认值)的表的序列当前值。
DO $$
DECLARE tablename varchar;
declare columnname varchar;
declare exsql varchar;
declare updateidvar varchar;
DECLARE resultId int;
declare info RECORD;
BEGIN
for info in SELECT table_schema||'.'||table_name as tablename,column_name
FROM information_schema.columns
WHERE table_schema = 'pip_pass' and column_default like 'nextval%'
loop
RAISE NOTICE '%,%',info.column_name,info.tablename;
exsql:= 'select '||'max('||info.column_name||') FROM '||info.tablename||' ';
RAISE NOTICE '%',exsql;
EXECUTE exsql INTO resultId;
RAISE NOTICE '%',resultId;
IF resultId > 0
then
updateidvar:='select setval('''||info.tablename||'_'||info.column_name||'_seq'', %s) from '||info.tablename||' ;';
EXECUTE format(updateidvar,resultId+1);
END IF;
end loop;
END;
$$
优化代码:
DO $$
DECLARE
info RECORD;
max_id bigint;
seq_name text;
found_sequence boolean := false;
sql text;
BEGIN
RAISE NOTICE '开始处理 pip_im 模式下的序列...';
-- 获取所有使用序列作为默认值的列
FOR info IN
SELECT
n.nspname as schema_name,
c.relname as table_name,
a.attname as column_name,
d.adsrc as default_value,
pg_get_expr(d.adbin, d.adrelid) as default_expr
FROM pg_attrdef d
JOIN pg_attribute a ON a.attrelid = d.adrelid AND a.attnum = d.adnum
JOIN pg_class c ON c.oid = a.attrelid
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname in ('pip_cdc','pip_im','pip_imdo','pip_pa','pip_pass','pip_pr','pip_public','pip_temp','pip_vbp')
--and c.relname='passim_history_message'
AND (d.adsrc LIKE 'nextval%' OR pg_get_expr(d.adbin, d.adrelid) LIKE 'nextval%')
ORDER BY n.nspname,c.relname, a.attname
LOOP
RAISE NOTICE '表: %.%, 列: %',
info.schema_name, info.table_name, info.column_name;
RAISE NOTICE '默认值: %', info.default_value;
RAISE NOTICE '默认表达式: %', info.default_expr;
-- 尝试方法1: 使用 pg_get_serial_sequence
EXECUTE format('SELECT pg_get_serial_sequence(%L, %L)',
info.schema_name || '.' || info.table_name,
info.column_name)
INTO seq_name;
IF seq_name IS NOT NULL THEN
RAISE NOTICE '方法1找到序列: %', seq_name;
found_sequence := true;
ELSE
-- 尝试方法2: 从默认值中提取序列名
RAISE NOTICE '方法1未找到序列,尝试从默认值中提取...';
-- 从默认表达式中提取序列名
IF info.default_expr IS NOT NULL AND info.default_expr LIKE 'nextval%' THEN
-- 提取序列名,处理不同的格式
seq_name := regexp_replace(
info.default_expr,
E'nextval\\s*\\(\\s*\'([^\']+)\'[^)]*\\)',
E'\\1'
);
-- 如果提取成功且没有模式前缀,加上模式前缀
IF seq_name IS NOT NULL AND seq_name <> info.default_expr THEN
-- 检查是否已经有模式前缀
IF position('.' in seq_name) = 0 THEN
seq_name := info.schema_name || '.' || seq_name;
END IF;
RAISE NOTICE '方法2提取序列: %', seq_name;
found_sequence := true;
END IF;
END IF;
END IF;
-- 如果找到了序列,进行处理
IF found_sequence THEN
-- 获取当前最大值
EXECUTE format('SELECT COALESCE(MAX(%I), 0) FROM %I.%I',
info.column_name, info.schema_name, info.table_name)
INTO max_id;
RAISE NOTICE '当前最大值: %', max_id;
IF max_id > 0 THEN
BEGIN
sql := format('SELECT setval(%L, %s, false)', seq_name, max_id + 1);
RAISE NOTICE '生成的SQL: %', sql;
EXECUTE sql;
RAISE NOTICE '✅ 已更新序列 % 为 %', seq_name, max_id + 1;
EXCEPTION WHEN OTHERS THEN
RAISE NOTICE '❌ 更新序列失败: %', SQLERRM;
END;
ELSE
BEGIN
sql := format('SELECT setval(%L, 1, false)', seq_name);
RAISE NOTICE '生成的SQL: %', sql;
EXECUTE sql;
RAISE NOTICE '✅ 已重置序列 % 为 1', seq_name;
EXCEPTION WHEN OTHERS THEN
RAISE NOTICE '❌ 重置序列失败: %', SQLERRM;
END;
END IF;
ELSE
RAISE NOTICE '⚠ 未找到关联的序列';
END IF;
RAISE NOTICE '---';
found_sequence := false;
END LOOP;
END;
$$;
三、解释说明
3.1 pg_sequences
pg_sequences 是 PostgreSQL 中的系统视图,用于集中展示数据库中所有序列(Sequence)的关键属性信息。其核心作用是简化序列的监控与管理,尤其在数据迁移、主键同步或性能优化场景中至关重要。
核心功能:序列元数据集中管理
pg_sequences 汇总了所有序列的配置和状态信息,主要字段包括:
-
schemaname 序列所属的模式(命名空间),如 public。
-
sequencename 序列的名称,例如 users_id_seq。
-
sequenceowner 序列的所有者(通常是创建该序列的数据库角色)。
-
start_value 序列的初始值(如 1)。
-
min_value / max_value 序列允许的最小值/最大值(如 1 和 9223372036854775807)。
-
increment_by 序列的步长(增量),通常为 1。
-
last_value 关键字段:序列最后一次持久化到磁盘的值(注意:若启用缓存,该值可能滞后于当前内存中的最新值)
3.2 应用场景
- 序列状态监控与修复 问题:批量导入数据后,序列的 last_value 可能小于表主键的最大值,导致主键冲突。 解决:通过 pg_sequences 快速定位需修复的序列,并执行:
SELECT setval('序列名', (SELECT MAX(id) FROM 表名) + 1);
-
跨数据库迁移验证 从 Oracle 迁移到 PostgreSQL 时,需确保序列属性(如起始值、步长)一致。 通过查询 pg_sequences 对比源库序列配置,避免因序列不同步引发主键冲突。
-
序列设计合理性检查 分析 min_value、max_value 和 last_value,预测序列剩余可用范围。 示例:若 last_value 接近 max_value,需及时扩展序列上限或重置,防止溢出错误。
-
权限与依赖关系审计 结合 pg_class 和 pg_depend 系统表,通过 sequencename 追溯序列关联的表、函数等对象,辅助安全审计。
3.3 脚本代码解析
目标定位
遍历 pip_pass 模式下所有包含 nextval 默认值的列(即使用序列作为主键或唯一标识的表):
SELECT table_schema||'.'||table_name, column_name
FROM information_schema.columns
WHERE table_schema = 'pip_pass' AND column_default LIKE 'nextval%'
动态 SQL 执行
为每个表生成查询最大值的 SQL:
exsql := 'SELECT max(' || info.column_name || ') FROM ' || info.tablename;
执行该 SQL 并存储结果到 resultId:
EXECUTE exsql INTO resultId;
序列值更新 若最大值 resultId > 0,则生成更新序列的 SQL:
updateidvar := 'SELECT setval(''' || info.tablename || '_' || info.column_name || '_seq'', %s)';
EXECUTE format(updateidvar, resultId + 1);
逻辑:将序列的下一个值设置为 当前最大值 + 1,确保新插入数据的主键不冲突。
评论
评论列表
暂无评论