为什么:自增主键把 ID 分配锁在单库序列上,分库分表时无法横向扩展。趁线上业务数据 近零(只有系统种子表有量)先改,代价最低。 - sql/schema.sql、sql/schema-phase1.sql、sql/partition-maintenance.sql:61 处 GENERATED BY DEFAULT AS IDENTITY 去掉,主键改 BIGINT 无默认值 - 52 个实体 @TableId IdType.AUTO -> IdType.ASSIGN_ID;两个入口 id-type: assign_id, 并加 global-config.sequence.worker-id/datacenter-id(单机固定值,多实例需按实例分配) - 新增 sql/migrate-s0-snowflake.sql:存量库幂等迁移,走 DROP IDENTITY 保留数据,不重建表 - 实测:三份建表脚本在新库连跑两遍幂等;线上 57 张表 identity 归零; watch_history/playback_ticket/order_event 的主键与唯一索引仍含分区键
50 lines
2.1 KiB
SQL
50 lines
2.1 KiB
SQL
-- Author: fruit.com.cn
|
||
--
|
||
-- S0 主键改雪花 · 存量库迁移(PostgreSQL 18)
|
||
--
|
||
-- 背景:第一阶段建表用的是 GENERATED BY DEFAULT AS IDENTITY(数据库自增序列),
|
||
-- 这会让 ID 分配集中在单库的序列上,一旦分库分表就无法横向扩展。
|
||
-- S0 把主键改成应用侧雪花 ID(MyBatis-Plus IdType.ASSIGN_ID),
|
||
-- DDL 侧只需要把 identity 去掉——序列不再需要。
|
||
--
|
||
-- 本脚本只做一件事:把所有 identity 列改成普通 BIGINT(**保留已有数据,不重建表**)。
|
||
-- 刻意不用 DROP TABLE / TRUNCATE,避免误伤存量数据。
|
||
-- 幂等:已经迁移过的库再跑一遍不做任何改动,NOTICE 里的数字会是 0。
|
||
--
|
||
-- 执行:psql -h 127.0.0.1 -U fruitshorts -d fruitshorts -f sql/migrate-s0-snowflake.sql
|
||
-- 复查:脚本末尾的注释 SQL(改写后应返回 0 行)
|
||
|
||
DO $$
|
||
DECLARE
|
||
r record;
|
||
v_done int := 0;
|
||
BEGIN
|
||
-- relispartition = false 表示"只处理顶层表":
|
||
-- 分区父表在 pg_class 里 relkind = 'p',月分区子表 relispartition = true;
|
||
-- identity 定义在父表上,子表跟着继承,所以逐个改子表是多余的。
|
||
FOR r IN
|
||
SELECT c.oid::regclass AS tbl, a.attname AS col
|
||
FROM pg_class c
|
||
JOIN pg_namespace n ON n.oid = c.relnamespace
|
||
JOIN pg_attribute a ON a.attrelid = c.oid
|
||
WHERE n.nspname = 'public'
|
||
AND c.relkind IN ('r', 'p')
|
||
AND c.relispartition = false
|
||
AND a.attidentity <> ''
|
||
AND a.attnum > 0
|
||
ORDER BY c.relname
|
||
LOOP
|
||
EXECUTE format('ALTER TABLE %s ALTER COLUMN %I DROP IDENTITY IF EXISTS', r.tbl, r.col);
|
||
v_done := v_done + 1;
|
||
END LOOP;
|
||
RAISE NOTICE 'S0 迁移完成:处理 % 个 identity 列(重复执行时为 0)', v_done;
|
||
END $$;
|
||
|
||
-- 复查用(结果应为 0 行):
|
||
-- SELECT c.relname, a.attname
|
||
-- FROM pg_class c
|
||
-- JOIN pg_namespace n ON n.oid = c.relnamespace
|
||
-- JOIN pg_attribute a ON a.attrelid = c.oid
|
||
-- WHERE n.nspname = 'public' AND a.attidentity <> ''
|
||
-- ORDER BY 1, 2;
|