Openstack 使用migrate進(jìn)行數(shù)據(jù)庫升級實(shí)現(xiàn)方案詳細(xì)介紹
OpenStack中隨著版本的切換,新版本加入一些數(shù)據(jù)庫表或者增加字段等是必然的事情,如何比較容易的進(jìn)行這些數(shù)據(jù)庫升級的適配和管理,這里就要用到oslo_db中的migrate了,這里以為M版本的heat為例,講解一下migrate管理db的原理。
我們使用migrate需要用到的主要包含以下兩部分:1.versions里面的為版本號+數(shù)據(jù)庫適配腳本;2.migrate.cfg為migrate需要用到的配置文件,兩部分的命名是固定的。

使用migrate進(jìn)行數(shù)據(jù)庫升級非常簡單,heat這邊提供了heat-manage db_sync, db_version的命令用來升級db以及查看當(dāng)前db的版本號,這里以執(zhí)行heat-manages db_sync,看下migrate的過程。
def db_sync(engine, version=None): path = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'migrate_repo') return oslo_migration.db_sync(engine, path, version, init_version=INIT_VERSION)
heat代碼的入口在這里,需要傳入engine用來連接db,version為我們需要升級到的版本,這里沒有傳,可以看到heat這邊是直接使用oslo_migrate的db_sync方法,我們看下三方庫中的這個(gè)方法。
def db_sync(engine, abs_path, version=None, init_version=0, sanity_check=True): """Upgrade or downgrade a database. Function runs the upgrade() or downgrade() functions in change scripts. :param engine: SQLAlchemy engine instance for a given database //連接數(shù)據(jù)庫 :param abs_path: Absolute path to migrate repository. //migrate倉庫的絕對路徑 :param version: Database will upgrade/downgrade until this version. //需要升級或者降級到的版本號,如果不傳則默認(rèn)升級到最新版本 If None - database will update to the latest available version. :param init_version: Initial database version //數(shù)據(jù)庫的初始版本號,會(huì)以該初始版本為起點(diǎn)升級 :param sanity_check: Require schema sanity checking for all tables //合理性檢查 """ if version is not None: try: version = int(version) except ValueError: raise exception.DBMigrationError(_("version should be an integer")) current_version = db_version(engine, abs_path, init_version) repository = _find_migrate_repo(abs_path) if sanity_check: _db_schema_sanity_check(engine) if version is None or version > current_version: migration = versioning_api.upgrade(engine, repository, version) else: migration = versioning_api.downgrade(engine, repository, version) if sanity_check: _db_schema_sanity_check(engine) return migration 代碼很清晰,簡潔。可以看到,整個(gè)過程就是先查詢下當(dāng)前db的版本,然后聲明一個(gè)migrate倉庫示例,對db做合理性檢查(主要是針對mysql),然后根據(jù)傳入的version和當(dāng)前的version決定是升級或者降低,最后再次檢查,整個(gè)migrate就完成了。
首先是查詢當(dāng)前數(shù)據(jù)庫的版本,
def db_version(engine, abs_path, init_version): """Show the current version of the repository. :param engine: SQLAlchemy engine instance for a given database :param abs_path: Absolute path to migrate repository :param init_version: Initial database version """ repository = _find_migrate_repo(abs_path) try: return versioning_api.db_version(engine, repository) except versioning_exceptions.DatabaseNotControlledError: meta = sqlalchemy.MetaData() meta.reflect(bind=engine) tables = meta.tables if len(tables) == 0 or 'alembic_version' in tables: db_version_control(engine, abs_path, version=init_version) return versioning_api.db_version(engine, repository) else: raise exception.DBMigrationError( _("The database is not under version control, but has " "tables. Please stamp the current version of the schema " "manually."))
新聞熱點(diǎn)
疑難解答
圖片精選