#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 迁移 customer_db/customers.json -> MySQL customer_profiles """ from __future__ import annotations import argparse import json from datetime import datetime from pathlib import Path import pymysql def get_conn(host: str, port: int, user: str, password: str, database: str): return pymysql.connect( host=host, port=port, user=user, password=password, database=database, charset="utf8mb4", autocommit=False, cursorclass=pymysql.cursors.DictCursor, ) def ensure_table(conn): with conn.cursor() as cur: cur.execute( """ CREATE TABLE IF NOT EXISTS customer_profiles ( customer_id VARCHAR(128) PRIMARY KEY, profile_json LONGTEXT NOT NULL, last_update DATETIME NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 """ ) cur.execute("SHOW INDEX FROM customer_profiles") exists = {str(r.get("Key_name", "")) for r in cur.fetchall()} if "idx_last_update" not in exists: cur.execute("CREATE INDEX idx_last_update ON customer_profiles(last_update)") conn.commit() def migrate(json_path: Path, host: str, port: int, user: str, password: str, database: str, truncate_target: bool): if not json_path.exists(): raise FileNotFoundError(f"customers.json 不存在: {json_path}") customers = json.loads(json_path.read_text(encoding="utf-8") or "{}") if not isinstance(customers, dict): raise RuntimeError("customers.json 格式错误,期望对象映射") conn = get_conn(host, port, user, password, database) try: ensure_table(conn) if truncate_target: with conn.cursor() as cur: cur.execute("TRUNCATE TABLE customer_profiles") conn.commit() now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") sql = ( "REPLACE INTO customer_profiles (customer_id, profile_json, last_update) " "VALUES (%s, %s, %s)" ) total = 0 with conn.cursor() as cur: for cid, profile in customers.items(): cur.execute(sql, (str(cid), json.dumps(profile, ensure_ascii=False), now)) total += 1 conn.commit() return total finally: conn.close() def main(): parser = argparse.ArgumentParser(description="迁移 customers.json 到 MySQL") parser.add_argument("--json-path", default=str(Path("customer_db") / "customers.json")) parser.add_argument("--host", required=True) parser.add_argument("--port", type=int, default=3306) parser.add_argument("--user", required=True) parser.add_argument("--password", required=True) parser.add_argument("--database", required=True) parser.add_argument("--truncate-target", action="store_true") args = parser.parse_args() total = migrate( json_path=Path(args.json_path), host=args.host, port=args.port, user=args.user, password=args.password, database=args.database, truncate_target=bool(args.truncate_target), ) print(f"[DONE] customer_profiles 写入 {total} 条") if __name__ == "__main__": main()