1

我想通过 alembic 更改我的 PostgreSQL 数据库中字符串列的大小。

我在本地数据库中的第一次尝试是更直接的方式,也是一种看起来合乎逻辑的方式:

更改我想要调整大小的 db.Column 字段的大小并配置 alembic 以查找类型更改,如此所述:将compare_type=True参数添加到context.configure()my alembic/env.py. 然后运行alembic revision --autogenerate其中正确生成的文件调用alter_column.

这似乎没问题,但是alembic upgrade head由于我取消了执行并寻找其他解决方案的 alter 列而花费了很多时间,因为我猜如果在我的计算机中花费这么长时间,那么在 Heroku 服务器中也会花费很长时间,我在此操作完成之前,我不会暂停我的服务。

所以我想出了一个在我的机器上完美运行的非常hacky的解决方案:

我在一个用于升级和降级的 alembic 文件中创建了我的更新语句:

connection = op.get_bind()


def upgrade():
    connection.execute("update pg_attribute SET atttypmod = 1000+4" + \
                       "where attrelid = 'item'::regclass and attname = 'details'", execution_options=None)


def downgrade():
    connection.execute("update pg_attribute SET atttypmod = 200+4" + \
                       "where attrelid = 'item'::regclass and attname = 'details'", execution_options=None)

在我的机器上工作得非常快。但是当将它推送到我在 Heroku 中的暂存应用程序并执行升级时,它会提示ERROR: permission denied for relation pg_attribute。如果我尝试直接在 psql 中执行更新语句,也会发生同样的情况。我想这是 Heroku 故意的,我不应该更新这类表,因为如果做错了可能会使数据库出现故障。我猜想在 Heroku 中强制更新不是要走的路。

我还尝试创建一个新的临时列,将旧小列中的所有数据复制到该临时列中,删除旧列,创建一个与旧列同名但具有所需大小的新列,复制临时列中的数据并以这种方式将其删除:

def upgrade():
    op.add_column('item', sa.Column('temp_col', sa.String(200)))
    connection.execute("update item SET temp_col = details", execution_options=None)
    op.drop_column('item', 'details')
    op.add_column('item', sa.Column('details', sa.String(1000)))
    connection.execute("update item SET details = temp_col", execution_options=None)
    op.drop_column('item', 'temp_col')


def downgrade():
    op.add_column('item', sa.Column('temp_col', sa.String(1000)))
    connection.execute("update item SET temp_col = details", execution_options=None)
    op.drop_column('item', 'details')
    op.add_column('item', sa.Column('details', sa.String(200)))
    connection.execute("update item SET details = temp_col", execution_options=None)
    op.drop_column('item', 'temp_col')

但这也需要很长时间,而且似乎不是一个真正整洁的方法。

所以我的问题是:在 Heroku 中通过 alembic 调整 postgreSQL 中的字符串列大小的正确方法是什么,而无需等待执行 alter 列的时间?

4

0 回答 0