diff --git a/backend/alembic/alembic.ini b/backend/alembic/alembic.ini index 37b1a50..160fab4 100644 --- a/backend/alembic/alembic.ini +++ b/backend/alembic/alembic.ini @@ -1,6 +1,12 @@ [alembic] script_location = alembic sqlalchemy.url = postgresql://scilit:scilit_dev@localhost:5432/scilit +# Commit each migration in its own transaction (default: whole upgrade in one). +# Rewrite-heavy migrations (JSON->JSONB / ALTER COLUMN TYPE DATE) on the +# 1.23M-row prod table peak at huge disk usage; one shared txn accumulates +# them -> disk-full (2026-08-10 batch 1 incident root cause). +# Independent commits release space early. +transaction_per_migration = true [loggers] keys = root,sqlalchemy,alembic diff --git a/backend/alembic/versions/1421ea169bb6_change_5_date_fields_to_date.py b/backend/alembic/versions/1421ea169bb6_change_5_date_fields_to_date.py index a58c009..a6db69e 100644 --- a/backend/alembic/versions/1421ea169bb6_change_5_date_fields_to_date.py +++ b/backend/alembic/versions/1421ea169bb6_change_5_date_fields_to_date.py @@ -21,19 +21,19 @@ DATE_FIELDS = ["pubmed_revised", "date_completed", "meshed_date", "create_date", def upgrade() -> None: - for col in DATE_FIELDS: - op.alter_column("global_literature", col, - existing_type=postgresql.TIMESTAMP(timezone=True), - type_=sa.Date(), - existing_nullable=True, - postgresql_using=f"{col}::date", - ) + # 合并为单条 ALTER:5 列一次全表重写。 + # 原实现循环逐个 ALTER = 5 次整表重写,同一事务内空间峰值叠加, + # 生产 123 万行表(~9.8GB)会爆盘(2026-08-10 批次 1 事故根因)。 + _cols = ", ".join( + f'ALTER COLUMN "{col}" TYPE DATE USING "{col}"::date' + for col in DATE_FIELDS + ) + op.execute(f"ALTER TABLE global_literature {_cols}") def downgrade() -> None: - for col in reversed(DATE_FIELDS): - op.alter_column("global_literature", col, - existing_type=sa.Date(), - type_=postgresql.TIMESTAMP(timezone=True), - existing_nullable=True, - ) + _cols = ", ".join( + f'ALTER COLUMN "{col}" TYPE TIMESTAMP WITH TIME ZONE' + for col in reversed(DATE_FIELDS) + ) + op.execute(f"ALTER TABLE global_literature {_cols}")