From 23be2f92968cee094f715f5d1c35eb32d60078b6 Mon Sep 17 00:00:00 2001 From: ryan Date: Tue, 30 Jun 2026 16:13:37 +0800 Subject: [PATCH] =?UTF-8?q?fix(db):=20=E6=96=B0=E5=A2=9E=20PostgreSQL=20?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E8=87=AA=E5=A2=9E=E5=BA=8F=E5=88=97?= =?UTF-8?q?=E5=85=A8=E5=B1=80=E5=90=8C=E6=AD=A5=E8=BF=81=E7=A7=BB=E8=84=9A?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为了解决因历史数据以显式 ID 方式迁移导致 PostgreSQL 自增序列计数器不同步,产生主键冲突唯一性约束报错(如 WAF 规则组和 IP 组保存失败)的问题,在 PostgreSQL 迁移中加入了对所有相关表 pg_get_serial_sequence 重置的代码。同时,在 SQLite 中补齐了对应的同名迁移文件。 --- docs/changelog/index.md | 4 ++++ ...202606300001_sync_all_legacy_sequences.sql | 20 +++++++++++++++++++ ...202606300001_sync_all_legacy_sequences.sql | 5 +++++ 3 files changed, 29 insertions(+) create mode 100644 internal/db/migrator/goose/postgres/202606300001_sync_all_legacy_sequences.sql create mode 100644 internal/db/migrator/goose/sqlite/202606300001_sync_all_legacy_sequences.sql diff --git a/docs/changelog/index.md b/docs/changelog/index.md index 15237525..f8ab87a2 100644 --- a/docs/changelog/index.md +++ b/docs/changelog/index.md @@ -18,6 +18,10 @@ sidebar: false ## [unreleased] +### 修复 + +- 修复 PostgreSQL 自增主键序列在历史数据迁移(INSERT 指定显式 ID)后与实际数据不同步的问题,通过新增全局序列同步脚本一键重置所有相关表的自增计数器。 + ## [v3.0.1] - 2026-06-30 ### 新增 diff --git a/internal/db/migrator/goose/postgres/202606300001_sync_all_legacy_sequences.sql b/internal/db/migrator/goose/postgres/202606300001_sync_all_legacy_sequences.sql new file mode 100644 index 00000000..3d8d5400 --- /dev/null +++ b/internal/db/migrator/goose/postgres/202606300001_sync_all_legacy_sequences.sql @@ -0,0 +1,20 @@ +-- +goose Up +SELECT setval(pg_get_serial_sequence('w_users', 'id'), GREATEST(COALESCE((SELECT MAX(id) FROM w_users), 0), 1), COALESCE((SELECT MAX(id) FROM w_users), 0) > 0); +SELECT setval(pg_get_serial_sequence('w_auth_sources', 'id'), GREATEST(COALESCE((SELECT MAX(id) FROM w_auth_sources), 0), 1), COALESCE((SELECT MAX(id) FROM w_auth_sources), 0) > 0); +SELECT setval(pg_get_serial_sequence('w_external_accounts', 'id'), GREATEST(COALESCE((SELECT MAX(id) FROM w_external_accounts), 0), 1), COALESCE((SELECT MAX(id) FROM w_external_accounts), 0) > 0); +SELECT setval(pg_get_serial_sequence('of_origins', 'id'), GREATEST(COALESCE((SELECT MAX(id) FROM of_origins), 0), 1), COALESCE((SELECT MAX(id) FROM of_origins), 0) > 0); +SELECT setval(pg_get_serial_sequence('of_apply_logs', 'id'), GREATEST(COALESCE((SELECT MAX(id) FROM of_apply_logs), 0), 1), COALESCE((SELECT MAX(id) FROM of_apply_logs), 0) > 0); +SELECT setval(pg_get_serial_sequence('of_proxy_routes', 'id'), GREATEST(COALESCE((SELECT MAX(id) FROM of_proxy_routes), 0), 1), COALESCE((SELECT MAX(id) FROM of_proxy_routes), 0) > 0); +SELECT setval(pg_get_serial_sequence('of_nodes', 'id'), GREATEST(COALESCE((SELECT MAX(id) FROM of_nodes), 0), 1), COALESCE((SELECT MAX(id) FROM of_nodes), 0) > 0); +SELECT setval(pg_get_serial_sequence('of_waf_rule_groups', 'id'), GREATEST(COALESCE((SELECT MAX(id) FROM of_waf_rule_groups), 0), 1), COALESCE((SELECT MAX(id) FROM of_waf_rule_groups), 0) > 0); +SELECT setval(pg_get_serial_sequence('of_waf_ip_groups', 'id'), GREATEST(COALESCE((SELECT MAX(id) FROM of_waf_ip_groups), 0), 1), COALESCE((SELECT MAX(id) FROM of_waf_ip_groups), 0) > 0); +SELECT setval(pg_get_serial_sequence('of_tls_certificates', 'id'), GREATEST(COALESCE((SELECT MAX(id) FROM of_tls_certificates), 0), 1), COALESCE((SELECT MAX(id) FROM of_tls_certificates), 0) > 0); +SELECT setval(pg_get_serial_sequence('of_managed_domains', 'id'), GREATEST(COALESCE((SELECT MAX(id) FROM of_managed_domains), 0), 1), COALESCE((SELECT MAX(id) FROM of_managed_domains), 0) > 0); +SELECT setval(pg_get_serial_sequence('of_dns_accounts', 'id'), GREATEST(COALESCE((SELECT MAX(id) FROM of_dns_accounts), 0), 1), COALESCE((SELECT MAX(id) FROM of_dns_accounts), 0) > 0); +SELECT setval(pg_get_serial_sequence('of_acme_accounts', 'id'), GREATEST(COALESCE((SELECT MAX(id) FROM of_acme_accounts), 0), 1), COALESCE((SELECT MAX(id) FROM of_acme_accounts), 0) > 0); +SELECT setval(pg_get_serial_sequence('of_pages_projects', 'id'), GREATEST(COALESCE((SELECT MAX(id) FROM of_pages_projects), 0), 1), COALESCE((SELECT MAX(id) FROM of_pages_projects), 0) > 0); +SELECT setval(pg_get_serial_sequence('of_pages_deployments', 'id'), GREATEST(COALESCE((SELECT MAX(id) FROM of_pages_deployments), 0), 1), COALESCE((SELECT MAX(id) FROM of_pages_deployments), 0) > 0); +SELECT setval(pg_get_serial_sequence('of_pages_deployment_files', 'id'), GREATEST(COALESCE((SELECT MAX(id) FROM of_pages_deployment_files), 0), 1), COALESCE((SELECT MAX(id) FROM of_pages_deployment_files), 0) > 0); + +-- +goose Down +SELECT 1; diff --git a/internal/db/migrator/goose/sqlite/202606300001_sync_all_legacy_sequences.sql b/internal/db/migrator/goose/sqlite/202606300001_sync_all_legacy_sequences.sql new file mode 100644 index 00000000..013e54ae --- /dev/null +++ b/internal/db/migrator/goose/sqlite/202606300001_sync_all_legacy_sequences.sql @@ -0,0 +1,5 @@ +-- +goose Up +SELECT 1; + +-- +goose Down +SELECT 1;