ikto/pg-migration-directories

用于安装/卸载/升级/降级PgSQL模式的工具

v1.0.0 2021-06-04 19:57 UTC

This package is not auto-updated.

Last update: 2024-09-22 10:45:40 UTC


README

简短描述

这个库受到 DBIx::Migration::Directories perl 模块启发。主要目标是提供一个小型平台,用于在PostgreSQL数据库上运行数据库迁移。然而,这个库不能直接使用。要使其工作,需要实现数据库连接适配器。此外,也可以改变这个工具的行为。

特性

  • 从头安装数据库模式(到空数据库中);
  • 执行SQL文件以升级/降级数据库模式;
  • 跟踪数据库模式版本;
  • 有机会选择任何方式连接到数据库(通过实现连接适配器),这使得其集成更加一致。

要求(环境)

  • PHP 7.0 或更高版本

工作原理:高级描述

简而言之,工作流程可以分解为几个步骤。

步骤1. 发现可用的迁移

首先,工具会获取一个可用的迁移列表。具体如何实现可以通过任何方式。发现和加载迁移的准确方式在迁移发现实现中描述。这个包包含最简单的一个:SqlFilesDiscovery。

SqlFilesDiscovery

为此发现,每个迁移都是一个目录,其中包含一些SQL文件。迁移目录应该具有以下布局

DBSCHEMANAME/
 Pg/
  00000001/
  00000001-00000002/
  00000002-00000001/
  00000002-00000003/
  00000003-00000002/

在顶层,有以db schema命名的目录,这是我们管理的:在这个例子中,我们管理名为 DBSCHEMANAME 的模式。每个里面都有一个 Pg 目录。在下一级,有一组以以下模式命名的目录:[from_version]-[to_version]。这些目录中的每一个代表单个迁移。换句话说,每个目录包含从一种版本到另一种版本更新数据库模式的指令(可能是升级或降级)。如果目录名只包含一个版本号,则它将被视为 0-[version]。零版本号表示数据库模式尚未安装。每个以版本命名的目录应该包含一组SQL文件。SQL文件的命名是任意的,但请注意,在执行迁移时,SQL文件将按字母顺序排序。

步骤2. 构建迁移路径

这一步骤非常简单。现有的数据库模式已经有一些版本(如果尚未安装,则为零)。用户/开发者提供要迁移到的版本(所需版本)。通过拥有发现的迁移列表、当前版本和所需版本,迁移路径构建器构建了需要应用以达到所需版本的确切迁移列表。通常不需要更改此行为,但这是可能的。

步骤3. 应用迁移

一个更简单的步骤。只剩下一件事情:将每个迁移应用到数据库中。从步骤2,我们有一个列表,所以这里我们只需遍历列表并应用每个迁移。

每个迁移都通过处理器应用。由SqlFilesDiscovery发现的迁移将通过SqlFilesProcessor应用。它按字母顺序排序SQL文件,加载SQL命令并按顺序执行它们。

代码示例

这个库不提供用于应用迁移的现成程序。以下示例显示了程序应该做什么。

use IKTO\PgMigrationDirectories\Database\DefaultManagedDatabase;
use IKTO\PgMigrationDirectories\Processor\DefaultProcessorFactory;
use IKTO\PgMigrationDirectories\Discovery\SqlFilesDiscovery;
use IKTO\PgMigrationDirectories\MigrationPathBuilder\MigrationPathBuilder;

/**
 * Step 0. Creating managed db object.
 */

// Here we create a connection adapter. This is just example and won't work of course.
$connection_adapter = new ConnectionAdapterInterface();
// Creating managed db.
$migration_db = new DefaultManagedDatabase($connection_adapter, 'DBSCHEMANAME', 'public');
// Setting processor factory.
// Processor factory is responsible for providing correct processor for migration.
// The DefaultProcessorFactory is shipped with this package and can be used
// if you don't create new types of migration definitions.
$migration_db->setProcessorFactory(new DefaultProcessorFactory());
// Specifying target db version. In real app it will come from config or something like this.
// This does not have real leverage and used just to be able to get this value later.
$migration_db->setDesiredVersion(42);

/**
 * Step 1. Discovering available migrations
 */
// Instantiating migrations discovery.
// This does not do real discovery. Real discovery will be triggered on the next step.
$discovery = new SqlFilesDiscovery(__DIR__ . '/sql/migrations', 'DBSCHEMANAME');

/**
 * Step 2. Building the migration path.
 */
// Retrieving current version number.
$startingVersion = $migration_db->getCurrentVersion();
// Instantiating migration path builder.
$builder = new MigrationPathBuilder($discovery);
// Creating migration path.
// Here we get desired version which we can in Step 0.
$path = $builder->getMigrationPath($startingVersion, $migration_db->getDesiredVersion());

/**
 * Step 3. Applying migration (choose one of two options here).
 */

// Applying migration path to the database (each step in separate transaction).
foreach ($path as $migration) {
    $migration_db->openTransaction();
    $migration_db->applyMigration($migration);
    $migration_db->commitTransaction();
    printf('Migrated from %d to %d', $migration->getStartingVersion(), $migration->getTargetVersion());
}

// Applying migration path to the database (whole migration is single transaction).
$migration_db->openTransaction();
foreach ($path as $migration) {
    $migration_db->applyMigration($migration);
    printf('Migrated from %d to %d', $migration->getStartingVersion(), $migration->getTargetVersion());
}
$migration_db->commitTransaction();

跟踪数据库模式版本

为了监控数据库的状态,库在数据库内部保留了关于迁移的数据。这些表应该在安装数据库模式的第一个迁移中创建。

CREATE TABLE migration_schema_version (
    name character varying(128) NOT NULL,
    version real NOT NULL,
    CONSTRAINT migration_schema_version_pkey PRIMARY KEY (name)
);
CREATE TABLE migration_schema_log (
    id serial NOT NULL,
    schema_name character varying(128) NOT NULL,
    event_time timestamp with time zone DEFAULT now() NOT NULL,
    old_version real DEFAULT 0 NOT NULL,
    new_version real NOT NULL,
    CONSTRAINT migration_schema_log_pkey PRIMARY KEY (id),
    CONSTRAINT migration_schema_log_schema_name_fkey FOREIGN KEY (schema_name)
        REFERENCES migration_schema_version (name) MATCH SIMPLE
        ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY IMMEDIATE
);

通常,这些表存储在 public 模式下。但您可以将它们存储在其他模式中,只是在创建管理数据库对象(或对应于状态管理器的参数)时,别忘了更改第三个构造函数参数。

此外,还可以以某种方式以不同的方式存储数据库模式版本,但此时需要替换状态管理器。要替换状态管理器,还需要替换管理数据库类。