You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
buffer_platform/app/migration.py

78 lines
2.5 KiB

"""
数据缓冲平台 - SQLite MySQL 数据迁移
"""
import logging
from sqlalchemy import create_engine
from sqlalchemy.orm import make_transient, sessionmaker
from app.config import DB_PATH
from app.models import MarketData, SymbolTimestamp
from app.mysql_database import MySQLSessionLocal
def _prepare_records_for_new_session(records):
"""将 ORM 实例转换为可在新 session 中插入的 transient 状态。"""
for record in records:
make_transient(record)
record.id = None
logger = logging.getLogger(__name__)
def migrate_sqlite_to_mysql():
"""从 SQLite 迁移 market_data 和 symbol_timestamps 数据到 MySQL。
幂等设计 MySQL 对应表已存在数据时直接跳过避免重复写入
返回 True 表示执行了迁移False 表示跳过或失败
"""
if MySQLSessionLocal is None:
logger.warning("MySQL 未初始化,跳过数据迁移")
return False
sqlite_engine = create_engine(
f"sqlite:///{DB_PATH}",
connect_args={"check_same_thread": False},
)
SQLiteSession = sessionmaker(bind=sqlite_engine)
mysql_session = MySQLSessionLocal()
try:
market_data_count = mysql_session.query(MarketData).count()
symbol_timestamp_count = mysql_session.query(SymbolTimestamp).count()
if market_data_count > 0 or symbol_timestamp_count > 0:
logger.info(
f"MySQL 已存在数据,跳过迁移 "
f"(market_data: {market_data_count}, symbol_timestamps: {symbol_timestamp_count})"
)
return False
sqlite_session = SQLiteSession()
try:
market_data_records = sqlite_session.query(MarketData).all()
symbol_timestamp_records = sqlite_session.query(SymbolTimestamp).all()
finally:
sqlite_session.close()
_prepare_records_for_new_session(market_data_records)
_prepare_records_for_new_session(symbol_timestamp_records)
if market_data_records:
mysql_session.add_all(market_data_records)
if symbol_timestamp_records:
mysql_session.add_all(symbol_timestamp_records)
mysql_session.commit()
logger.info(
f"迁移完成: market_data: {len(market_data_records)} 条, "
f"symbol_timestamps: {len(symbol_timestamp_records)}"
)
return True
except Exception as e:
logger.error(f"数据迁移失败: {e}")
mysql_session.rollback()
return False
finally:
mysql_session.close()