| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- """
- 修复 PostgreSQL 序列不同步问题。
- 当表中存在手动插入的数据时,自增序列会落后于实际最大 ID,
- 导致后续 INSERT 报 UniqueViolation。
- """
- import os
- from dotenv import load_dotenv
- load_dotenv()
- DB_HOST = os.environ.get("DB_HOST", "localhost")
- DB_PORT = int(os.environ.get("DB_PORT", 5432))
- DB_USER = os.environ.get("DB_USER", "")
- DB_PASSWORD = os.environ.get("DB_PASSWORD", "")
- DB_NAME = os.environ.get("DB_NAME", "")
- TABLES = [
- "spider_task", # collection_task
- "ai_conversation",
- "spider_result",
- "deep_collection",
- "ai_model",
- "token_usage_log",
- "ai_message",
- "user",
- "spider_source",
- "knowledge_import_task",
- ]
- def fix_sequences():
- import psycopg2
- uri = f"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}"
- print(f"Connecting to {DB_HOST}:{DB_PORT}/{DB_NAME} as {DB_USER}...")
- conn = psycopg2.connect(
- host=DB_HOST,
- port=DB_PORT,
- user=DB_USER,
- password=DB_PASSWORD,
- dbname=DB_NAME,
- )
- conn.autocommit = True
- cur = conn.cursor()
- fixed = []
- skipped = []
- for table in TABLES:
- seq = f"{table}_id_seq"
- try:
- # 检查序列是否存在
- cur.execute(
- "SELECT EXISTS (SELECT 1 FROM information_schema.sequences WHERE sequence_name = %s)",
- (seq,),
- )
- exists = cur.fetchone()[0]
- if not exists:
- skipped.append(table)
- continue
- # 获取当前序列值和表最大 ID
- cur.execute(f"SELECT last_value FROM {seq}")
- seq_val = cur.fetchone()[0]
- cur.execute(f"SELECT COALESCE(MAX(id), 0) FROM {table}")
- max_id = cur.fetchone()[0]
- if max_id > seq_val:
- cur.execute(f"SELECT setval('{seq}', {max_id})")
- fixed.append(f"{table}: seq {seq_val} -> {max_id}")
- else:
- skipped.append(f"{table}: seq={seq_val}, max_id={max_id} (OK)")
- except Exception as e:
- skipped.append(f"{table}: ERROR - {e}")
- cur.close()
- conn.close()
- print("\n--- 修复结果 ---")
- for item in fixed:
- print(f" [FIXED] {item}")
- for item in skipped:
- print(f" [OK ] {item}")
- if fixed:
- print(f"\n共修复 {len(fixed)} 个表的序列。")
- else:
- print("\n所有序列均正常,无需修复。")
- if __name__ == "__main__":
- fix_sequences()
|