python - 使用 automap_base 和 alembic 迁移/复制数据库
问题描述
我有一个数据库x
,每个表中都填充了一些数据。我想创建该数据库的副本(具有相同的架构和确切的数据)。首先,我创建了一个使用 automap_base 的声明性基类x
。
from sqlalchemy.ext.automap import automap_base
from sqlalchemy.orm import Session as s
def name_for_scalar_relationship(base, local_cls, referred_cls, constraint):
name = referred_cls.__name__.lower() + "_ref"
return name
Base = automap_base()
# engine, refering to the original database
engine = create_engine("mysql+pymysql://root:password1@localhost:3306/x")
# reflect the tables
Base.prepare(engine, reflect=True, name_for_scalar_relationship=name_for_scalar_relationship)
Router = Base.classes.router
########check the data in Router table
session = s(engine)
r1 = session.query(Router).all()
for n in r1:
print(n.name) #This returns all the router names
从这里获得一些帮助,我alembic
用来升级y
位于不同位置的数据库mysql+pymysql://anum:Anum-6630@localhost:3306/y
。
from sqlalchemy.orm import sessionmaker as sm
from sqlalchemy import create_engine
from alembic import op
# revision identifiers, used by Alembic.
revision = 'fae98f65a6ff'
down_revision = None
branch_labels = None
depends_on = None
def upgrade():
bind = op.get_bind()
session = sm(bind=bind)
Base.metadata.create_all(bind=bind)
# session._add_bind(session, bind=bind)
session.add(Router(id=uuid.uuid().bytes, serial="Test1"))
session.commit()
该行Base.metadata.create_all(bind=bind)
实际上将所有表(包括正确的 FK 约束)添加到 database y
,但所有表都是空的,除了我手动添加的 Router 表中的一个条目。我尝试使用 create_all() 但这并没有奏效。有没有办法将所有数据复制x
到y
数据库?
解决方案
由于没有人回答,这是我进行复制的狂野方法:因为需要按顺序创建表(以避免 FK 约束错误),所以我必须定义一个包含每个表的有序列表
缓慢且不可靠的解决方案:
allTables = ["tableA",
"tableB", # <table B points to FK constraint of tableA>
"tableC", # <table C points to FK constraint of tableB>
...]
def copyAllContent():
global allTables
s = Session(bind=origEngine) # session bind to original table
se = Session(bind=op.get_bind()) # session bind to cloned table (currently empty)
try:
for table in allTables:
# print(table)
rows = s.query(Base.classes._data[table]).all()
for row in rows:
local_object = se.merge(row) #merging both sessions
se.add(local_object)
se.commit()
except Exception as e:
print(e)
上述方法适用于大多数表,但不是全部。例如router
,原始数据库中存在表,但我仍然收到错误,s.query(Base.classes._data[table]).all()
因为 name 不存在键router
。没有足够的时间来挖掘解决方案。
快速可靠的解决方案:
后来我从这里找到了另一个快速且安静可靠的解决方案,使用mysqldump
#copy sql dump from x database
mysqldump --column-statistics=0 -P 8000 -h localhost -u root -p --hex-blob x > x_dump.sql
上面的命令行mysqldump
命令创建一个名为的 sql 转储文件x_dump.sql
,其中包含重新生成数据库所需的所有必要 SQL 脚本。现在我们需要做的就是将此 sql 转储文件应用到另一个数据库y
#clone the database contents into y database
mysql -P 3306 -h localhost -u anum -p y < x_dump.sql
这是做同样事情的pythonic版本
import subprocess
#copy sql dump from x database - blocking call (use Popen for non-blocking)
print(subprocess.call(["mysqldump", "--column-statistics=0", '-P', '8000', '-h', 'localhost', '-u', '<user>', '-p<password>',
'--hex-blob', 'x', '>', 'x_dump.sql'], shell=True))
print("done taking dump.")
#clone the database contents into y database - blocking call
print(subprocess.call(["mysql", '-P', '3306', '-h', 'localhost', '-u', '<user>', '-p<password>',
'y', '<', 'x_dump.sql'], shell=True))
print("done cloning the sqlDump.")
推荐阅读
- moqui - orderby lastUpdatedStamp in entity-find
- database - 实体、实体类型和实体实例之间有什么区别?
- python - 什么是 Python“系统库”?
- python - python docker如何打印脚本的返回码以了解测试脚本是通过还是失败
- python - Flask - 每个 HTTP 请求似乎都不是一个新的独立请求。这是为什么?
- python - Python pathlib:解析符号链接的完整路径而不遵循它
- linux - 是否可以从 x86(x64) windows 交叉编译到 x86(x64) linux?
- amazon-dynamodb - 如何使用带有 dynamodb 的 aws cli 查询名称包含“:”的索引?
- java - 在 JAVA 中使用实际 API 调用模拟测试支付的最佳实践是什么
- python - 替换 Python String 中 2 个数组的值