ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

MikroORM 数据库迁移完全指南:从 Schema 快照到多租户运行时 Schema 上下文

MikroORM 数据库迁移完全指南:从 Schema 快照到多租户运行时 Schema 上下文 后端【免费下载链接】mikro-ormTypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, MariaDB, MS SQL Server, PostgreSQL and SQLite/libSQL databases.项目地址https://gitcode.com/gh_mirrors/mi/mikro-orm点击查看免费下载MikroORM 内置了基于 Schema 差异schema diff的迁移系统它根据当前实体元数据与目标数据库 schema 之间的差异自动生成迁移文件并支持事务包裹、执行日志表、schema 快照比对以及面向多租户场景的运行时 schema 上下文runtime schema context。本文以mikro-orm/migrationsSQL 驱动与mikro-orm/migrations-mongodbMongoDB两个扩展包为主线完整覆盖迁移类编写、初始迁移、快照机制、全部配置项、CLI 与编程式用法、自定义生成器及调试手段并辅以本仓库 packages/migrations 与 packages/migrations-mongodb 的源码实现佐证帮助你把这套迁移体系真正落地到开发、测试与生产环境。认识迁移系统扩展注册与核心机制MikroORM 的迁移能力通过扩展extension注入使用前需要安装对应驱动类型的迁移包并在 ORM 配置中注册Migratorimport { Migrator } from mikro-orm/migrations; // 或 mikro-orm/migrations-mongodb export default defineConfig({ // ... extensions: [Migrator], })SQL 驱动PostgreSQL、MySQL、MariaDB、MSSQL、SQLite/libSQL 等使用mikro-orm/migrationsMongoDB 使用独立的mikro-orm/migrations-mongodb。注册后orm.migrator便可用其实现位于 packages/migrations/src/Migrator.ts继承自 core 包中的 AbstractMigratorregister()方法把 migrator 注册为 ORM 扩展。几个贯穿全文的基础事实迁移文件不携带扩展名存储MigrationStorage在读写执行日志时通过getMigrationName()去掉.js/.ts后缀见 MigrationStorage.ts因此同一迁移在 TS 源码与编译产物之间共享同一个记录名。默认事务包裹每条迁移默认在独立事务中执行且整批迁移会被包裹进一个主事务master transaction。任一迁移失败整批全部回滚。这由MigrationRunner实现非事务模式直接串行执行查询事务模式则通过connection.transactional()并以ctx: this.#masterTransaction汇入主事务见 MigrationRunner.ts。执行日志表默认表名为mikro_orm_migrations包含id自增主键、name、executed_at三列由MigrationStorage.ensureTable()按需创建见 MigrationStorage.ts。编写第一个迁移Migration 类迁移是继承抽象类Migration的类实现up()方法可选择性实现down()import { Migration } from mikro-orm/migrations; export class Migration20191019195930 extends Migration { async up(): Promisevoid { this.addSql(select 1 1); } }要点down()默认抛错This migration cannot be reverted见 Migration.ts只有显式实现down()的迁移才支持回滚。isTransactional(): boolean默认返回true可在单个迁移上覆写实现这条迁移不进事务的定制行为Migration.ts。Configuration对象与驱动实例在Migration类上下文中可用——基类构造器即接收driver与configMigration.ts。this.execute(sql, params?)直接执行原生 SQL且与迁移的其余查询共享同一事务上下文ctxMigration.ts。this.addSql()除字符串外还接受NativeQueryBuilder原生查询构建器实例或raw()SQL 片段Query联合类型定义于 Migration.ts。在迁移中使用 EntityManager迁移的主要职责是修改 SQL schema但也可用于数据修改方式有二this.execute()原生 SQL或通过 EntityManagerimport { Migration } from mikro-orm/migrations; import { User } from ../entities/User; export class Migration20191019195930 extends Migration { async up(): Promisevoid { const em this.getEntityManager(); em.create(User, { ... }); await em.flush(); } }:::warning 在迁移中使用EntityManager是可行的但不推荐它依赖当前检出代码的实体元数据而非生成迁移那一刻的状态一旦元数据随时间演进旧迁移可能出错。优先在迁移中使用原生查询。 :::getEntityManager()返回一个缓存且已绑定当前事务上下文的 EM 实例setTransactionContext(this.ctx)源码见 Migration.ts。初始迁移实体与 schema 均已存在时当项目已经有现成数据库 schema想引入迁移体系时用--initial创建初始迁移npx mikro-orm migration:create --initial约束与行为仅当此前从未生成或执行过任何迁移时可用Migrator.validateInitialMigration()会先检查 executed 与 pending 列表非空即抛错Migrator.ts。初始迁移内容等价于schema:create的 schema 转储即getCreateSchemaSQL()的完整建表脚本见 Migrator.ts。若数据库已存在实体对应的全部表迁移会被自动标记为已执行storage.logMigration见 Migrator.ts若只存在部分表则抛错提示先清理这些表。快照机制基于目标 Schema 而非数据库创建新迁移时系统会把目标 schema 快照自动保存到迁移文件夹中。之后创建迁移时以该快照为 diff 基准而不是实时读取数据库——这意味着即使你还没执行 pending 迁移也能生成正确的 schema 差异。快照文件由两条不同来源写入migration:create及--initial由实体元数据推导的目标 schemastoreCurrentSchema()默认取getTargetSchema()migration:up/migration:down迁移应用后通过数据库 introspection 重写快照Migrator.ts。两条路径对同一 schema 产生相同的序列化形态因此migration:create之后执行迁移通常不会产生有意义的快照重写但部分数据库特有的细节如 PostgreSQL 的int与int4类型别名仍可能产生细微 diff。runMigrations()中有一个细节值得注意若 introspection 结果与现有快照在SchemaComparator语义上一致则跳过重写避免把表达式大小写、索引方法等外观噪声写进 diffMigrator.ts。快照文件应像迁移文件一样纳入版本控制默认命名为.snapshot-dbName.json可由snapshotName覆盖路径解析见 Migrator.ts。通过migrations.snapshot: false可关闭快照。若希望快照只描述实体元数据设migrations.snapshotOnMigrate: false跳过migration:up/migration:down的 introspection 重写。注意关闭后快照不再跟随数据库migration:down之后执行migration:create仍会对比回滚前的状态产生空 diff此时应改用migration:up重新应用既有迁移而不是重新生成。配置详解pattern选项已被glob取代migrations.path与migrations.pathTs的工作方式与实体发现中的entities/entitiesTs一致后者存在时优先于前者见 Migrator.ts 中快照路径的解析逻辑。await MikroORM.init({ // 默认值 migrations: { tableName: mikro_orm_migrations, path: ./migrations, pathTs: undefined, glob: !(*.d).{js,ts,cjs}, silent: false, transactional: true, disableForeignKeys: false, allOrNothing: true, dropTables: true, safe: false, snapshot: true, snapshotOnMigrate: true, emit: ts, generator: TSMigrationGenerator, fileName: (timestamp: string, name?: string) Migration${timestamp}${name ? _ name : }, }, })以上默认值与 packages/core/src/utils/Configuration.ts 中MigrationsOptions的类型定义一一对应可按需覆写。可用选项速查表选项说明tableName: string存储迁移执行日志的数据库表名默认mikro_orm_migrations。也支持schema.tableName形式MigrationStorage.resolveTableName()会解析出 schema 部分见 MigrationStorage.ts。path: string存放编译后迁移文件的目录默认./migrations生产环境应指向 JS 文件。pathTs: string存放 TypeScript 迁移源码的目录开发期配合tsx等使用若指定path应指向编译输出。glob: string匹配迁移文件的 glob默认!(*.d).{js,ts,cjs}匹配除.d.ts外的全部.js/.ts/.cjs。silent: boolean是否抑制迁移执行日志默认false。transactional: boolean是否将每条迁移包裹在事务中默认true。设为false时迁移不再自动进入事务。disableForeignKeys: boolean迁移期间是否禁用外键检查默认false。为true时会在语句前后包裹set foreign_key_checks 0等价的开启/恢复语句由SchemaHelper.getSchemaBeginning/getSchemaEnd拼接见 MigrationRunner.ts。allOrNothing: boolean是否把所有迁移包进一个主事务默认true任一迁移失败则全部回滚。dropTables: boolean是否允许在迁移中删表默认true为false时跳过删表操作。safe: boolean安全模式默认false为true时同时禁用删表与删列。snapshot: boolean创建新迁移时是否保存 schema 快照默认true。快照辅助 diff应随迁移文件一起纳入版本控制。snapshotOnMigrate: boolean执行迁移时是否从数据库 introspection 更新快照默认true设为false后快照仅由migration:create管理。snapshotName: string快照文件自定义名称默认基于迁移时间戳生成。emit: js \| ts \| cjs生成迁移文件的格式默认ts。emit还会决定使用TSMigrationGenerator还是JSMigrationGenerator见 Migrator.ts。generator: ConstructorIMigrationGenerator生成迁移文件内容的生成器类默认TSMigrationGenerator可自定义格式化与结构。fileName: (timestamp: string, name?: string) string迁移文件名生成函数接收时间戳与可选名称默认Migration${timestamp}${name ? _ name : }。migrationsList: (MigrationObject \| ConstructorMigration)[]迁移对象/类数组替代基于文件系统的发现机制适合打包bundled场景。schema: string运行迁移的目标 schema。设置后每条迁移前会执行驱动的 set current schema 语句跟踪表也位于该 schema。参见下方「运行时 schema 上下文」。MSSQL 不支持。includeWildcardSchema: boolean为true时schema: *的实体被纳入migration:create输出并生成不带限定符的 DDL从而可经由migrator.up({ schema })应用于任意 schema默认false。示例配置await MikroORM.init({ migrations: { tableName: my_migrations, path: dist/migrations, pathTs: src/migrations, glob: *.{js,ts}, silent: false, transactional: true, disableForeignKeys: true, allOrNothing: true, dropTables: false, // 出于安全禁用删表 safe: false, snapshot: true, emit: ts, fileName: (timestamp, name) ${timestamp}_${name || migration}, }, });环境变量覆盖上述选项也可通过环境变量覆盖机制见 docs/versioned_docs/version-7.2/configuration.md#using-environment-variablesMIKRO_ORM_MIGRATIONS_TABLE_NAMEMIKRO_ORM_MIGRATIONS_PATHMIKRO_ORM_MIGRATIONS_PATH_TSMIKRO_ORM_MIGRATIONS_GLOBMIKRO_ORM_MIGRATIONS_TRANSACTIONALMIKRO_ORM_MIGRATIONS_DISABLE_FOREIGN_KEYSMIKRO_ORM_MIGRATIONS_ALL_OR_NOTHINGMIKRO_ORM_MIGRATIONS_DROP_TABLESMIKRO_ORM_MIGRATIONS_SAFEMIKRO_ORM_MIGRATIONS_SILENTMIKRO_ORM_MIGRATIONS_EMITMIKRO_ORM_MIGRATIONS_SNAPSHOTMIKRO_ORM_MIGRATIONS_SNAPSHOT_ON_MIGRATEMIKRO_ORM_MIGRATIONS_SNAPSHOT_NAME在生产环境运行迁移生产环境应使用编译后的迁移文件几乎开箱即用只需正确配置路径import { MikroORM, Utils } from mikro-orm/core; await MikroORM.init({ migrations: { path: dist/migrations, pathTs: src/migrations, }, // 或二选一 // migrations: { // path: Utils.detectTypeScriptSupport() ? src/migrations : dist/migrations, // }, // ... });这样在 CLI 中通常开启 TS 支持生成 TS 迁移文件而在生产环境使用编译后的 JS 文件。MigrationGenerator.generate()会按emit选项在pathTs与path之间选择输出目录并以baseDir为基准做路径归一化与目录创建MigrationGenerator.ts。使用自定义 MigrationGenerator生成新迁移时MigrationGenerator负责产出文件内容你可以提供自己的实现来做 SQL 格式化等定制import { TSMigrationGenerator } from mikro-orm/migrations; import { format } from sql-formatter; class CustomMigrationGenerator extends TSMigrationGenerator { generateMigrationFile(className: string, diff: { up: string[]; down: string[] }): string { const comment // this file was generated via custom migration generator\n\n; return comment super.generateMigrationFile(className, diff); } createStatement(sql: string, padLeft: number): string { sql format(sql, { language: postgresql }); // 一点缩进魔法 sql sql.split(\n).map((l, i) i 0 ? l : ${ .repeat(padLeft 13)}${l}).join(\n); return super.createStatement(sql, padLeft); } } await MikroORM.init({ // ... migrations: { generator: CustomMigrationGenerator, }, });生成器基类MigrationGenerator会生成形如Migration20230421212713的类名时间戳来自new Date().toISOString().replace(/[-T:]|\.\d{3}z$/gi, )见 MigrationGenerator.ts而默认的 TSMigrationGenerator 产出的文件会自动带上override name ...与up()/down()骨架createStatement会对 SQL 中的反引号、$、反斜杠做转义后包进this.addSql(\...)。使用 CLI 管理迁移npx mikro-orm migration:create # 用当前 schema 差异创建新迁移 npx mikro-orm migration:up # 迁移到最新版本 npx mikro-orm migration:down # 向下迁移一步 npx mikro-orm migration:list # 列出所有已执行的迁移 npx mikro-orm migration:check # 检查 schema 是否最新 npx mikro-orm migration:pending # 列出所有待执行的迁移 npx mikro-orm migration:fresh # 删除数据库并迁移到最新版本 npx mikro-orm migration:log # 将迁移标记为已执行但不运行 npx mikro-orm migration:unlog # 从已执行列表移除迁移但不回滚 npx mikro-orm migration:rollup # 将所有已执行迁移合并为单个迁移创建空白迁移文件可用npx mikro-orm migration:create --blank生成的up()/down()为占位的select 1见 Migrator.ts。migration:up与migration:down支持--from-f、--to-t、--only-o选项只运行迁移的子集npx mikro-orm migration:up --from 2019101911 --to 2019102117 # 同上 npx mikro-orm migration:up --only 2019101923 # 只应用单个迁移 npx mikro-orm migration:down --to 0 # 向下回滚所有迁移运行 TS 迁移文件时请确保项目安装了tsxCLI 会自动使用它。migration:fresh支持--seed在迁移后播种数据npx mikro-orm migration:fresh --seed # 使用默认 seeder 播种 npx mikro-orm migration:fresh --seedUsersSeeder # 使用 UsersSeeder 播种默认 seeder 可在 orm 配置中用config.seeder.defaultSeeder指定。migration:rollup会把所有已执行迁移合并为一个迁移文件适合清理长期积累的大量迁移。它通过抽取每个迁移up()/down()方法中的源码并拼接成新文件实现——除更新迁移日志外不触碰数据库因此没有数据丢失风险。CLI 侧的参数解析与分发位于 packages/cli/src/commands/MigrationCommandFactory.ts。编程式使用 Migrator也可以在脚本中直接初始化 MikroORM 并调用orm.migratorimport { MikroORM } from mikro-orm/core; import { Migrator } from mikro-orm/migrations; (async () { const orm await MikroORM.init({ extensions: [Migrator], dbName: your-db-name, // ... }); await orm.migrator.create(); // 创建文件 Migration20191019195930.ts await orm.migrator.up(); // 迁移到最新 await orm.migrator.up(name); // 只向上运行指定迁移 await orm.migrator.up({ to: up-to-name }); // 迁移到指定版本 await orm.migrator.down(); // 向下迁移一步 await orm.migrator.down(name); // 只向下运行指定迁移 await orm.migrator.down({ to: down-to-name }); // 向下迁移到指定版本 await orm.migrator.down({ to: 0 }); // 回滚到第一个版本 await orm.migrator.rollup(); // 把所有已执行迁移合并为一个 await orm.migrator.rollup([Migration1, Migration2]); // 合并指定迁移 await orm.migrator.up({ schema: tenant_42 }); // 针对特定 schema 运行见运行时 schema 上下文 await orm.close(true); })();然后用tsx运行或编译为纯 JS 后使用node$ tsx migratecreate()返回{ fileName, code, diff }当 diff 为空时返回空文件名与空代码Migrator.ts。getPending()在快照存在时会走快照路径数据库不可达时把发现的迁移全部视为 pendingMigrator.ts。提供事务上下文某些场景下你可能想自己控制事务上下文await orm.em.transactional(async em { await migrator.up({ transaction: em.getTransactionContext() }); });AbstractMigrator的MigrateOptions支持from/to/migrations/transaction/schema五个维度见 AbstractMigrator.tsto归一化后既可以是迁移名也可以是0回滚全部。运行时 schema 上下文一套迁移、多个 Schema默认情况下迁移针对 SQL 中烘焙的 schema无限定符的 DDL 则针对连接默认 schema运行。运行时 schema 上下文允许你把既有迁移重定向到另一个 schema 而无需重新生成——适合每部署一个 schema如 PR 预览环境以及把同一套迁移扩散到多个租户 schema。解析到运行时 schema 时migrator 会在每条迁移前插入驱动的 set current schema 语句并在finally中复位resetSessionSchema见 MigrationRunner.ts避免连接池中的连接滞留在迁移目标 schema。迁移跟踪表跟随同一 schema因此每个目标都拥有独立的迁移历史MigrationStorage的resolveTableName()优先取#runSchema见 MigrationStorage.ts。驱动SetResetPostgreSQLSET search_path TO xRESET search_pathMySQL / MariaDBUSE xUSE config.dbNameOracleALTER SESSION SET CURRENT_SCHEMA xALTER SESSION SET CURRENT_SCHEMA dbNameMSSQL不支持——抛错—SQLite / libSQL无 schema 概念——静默无操作—每部署一个 schema在 ORM 配置中设置migrations.schema既有无限定符迁移即在指定 schema 中执行跟踪表同在await MikroORM.init({ migrations: { schema: process.env.PR_PREVIEW_SCHEMA, // 例如 pr_1234 }, });多租户扩散通过migrations.includeWildcardSchema把通配符实体纳入migration:create再用migrator.up({ schema })应用生成的无限定符迁移await MikroORM.init({ migrations: { includeWildcardSchema: true, }, }); for (const tenant of tenants) { await orm.migrator.up({ schema: tenant }); }不修改全局配置也能查看单个租户的迁移状态await orm.migrator.getExecuted({ schema: tenant_42 }); await orm.migrator.getPending({ schema: tenant_42 });租户编排与失败恢复由调用方负责——migrator 暴露的是按 schema 的原语而非托管的多租户运行器。:::caution 要让migration:create生成无限定符 DDL生成迁移时既不能设置options.schema也不能设置config.schema。若设置了config.schema通配符表会被加上该 schema 限定本地开发时有用。请在没有config.schema的环境中生成迁移再以migrator.up({ schema })应用。 :::CLI 支持migration:up与migration:down都接受--schema别名-s标志npx mikro-orm migration:up --schema tenant_42 npx mikro-orm migration:down --schema tenant_42注意事项public并非隐式可用search_path或等价物只指向目标 schema——引用public中的扩展或共享查询必须显式限定。数据隔离部署PR 预览、租户不会意外读写public。要求事务化迁移运行时 schema 与transactional: false或迁移覆写isTransactional()为false组合会抛错——没有固定事务时每条语句可能落在不同的池化连接上set/reset 无法覆盖 DDL该检查位于 MigrationRunner.ts。仅支持顺序扩散migrator.up({ schema })会把目标 schema 作为实例状态存于共享的MigrationRunner/MigrationStorage。在同一 ORM 实例上执行Promise.all([orm.migrator.up({ schema: a }), orm.migrator.up({ schema: b })])会交错 set/reset不受支持。真正需要并行部署时请使用独立进程各自MikroORM.init。migrations.schema不回退到config.schema它是 migrator 专属的 opt-in 选项。MongoDBMongo migrator 在传入{ schema }时会抛出明确错误而非静默忽略。静态导入迁移打包场景若不想动态导入目录例如用 webpack 打包代码可以直接静态导入迁移。可以用显式迁移名或用隐式的文件名作为迁移名import { MikroORM } from mikro-orm/core; import { Migrator } from mikro-orm/migrations; import { Migration20191019195930 } from ../migrations/Migration20191019195930.ts; import { Migration20191019195931 } from ../migrations/Migration20191019195931.ts; await MikroORM.init({ extensions: [Migrator], migrations: { migrationsList: [ // 显式迁移名 { name: CustomMigrationName, class: Migration20191019195930, }, // 隐式迁移名 Migration20191019195931 ], }, });直接传入的迁移类未带显式名会先取迁移实例的name属性解析名称再回退到类名。新生成的迁移会自动设置name属性——因为压缩器可能混淆类名同一应用在压缩与非压缩构建下迁移会以不同名字记录到迁移表。如果你的迁移文件早于该机制且打包时启用压缩请手动补上属性export class Migration20191019195930 extends Migration { override name Migration20191019195930; // ... }借助 webpack 的 context module API可以动态导入整个文件夹的迁移import { MikroORM } from mikro-orm/core; import { Migrator } from mikro-orm/migrations; import { basename } from path; const migrations {}; function importAll(r) { r.keys().forEach( (key) (migrations[basename(key)] Object.values(r(key))[0]) ); } importAll(require.context(../migrations, false, /\.ts$/)); const migrationsList Object.keys(migrations).map((migrationName) ({ name: migrationName, class: migrations[migrationName], })); await MikroORM.init({ extensions: [Migrator], migrations: { migrationsList, }, });自定义迁移命名用--nameCLI 选项指定迁移名会追加到生成前缀之后# 生成文件 Migration20230421212713_add_email_property_to_user_table.ts npx mikro-orm migration:create --nameadd_email_property_to_user_table通过fileName回调可定制命名约定甚至强制迁移必须带名字migrations: { fileName: (timestamp: string, name?: string) { // 强制用户提供名字否则会得到 Migration20230421212713_undefined if (!name) { throw new Error(Specify migration name via mikro-orm migration:create --name...); } return Migration${timestamp}_${name}; }, },:::caution 覆写migrations.fileName时务必保证迁移文件可排序——永远不要让文件名以自定义name开头否则可能导致执行顺序错误。 :::MongoDB 支持MongoDB 迁移使用独立包mikro-orm/migrations-mongodb其余与现有 CLI 命令兼容。使用this.getCollection()或this.getDb()操作数据库。:::warning 迁移中应避免使用实体类引用——实体定义会随版本演进从而破坏旧迁移。请改用this.getCollection()的集合字符串名或经this.getDb()使用原始Db实例。 :::可用方法MongoDB 的Migration类提供以下助手实现见 packages/migrations-mongodb/src/Migration.tsthis.getCollection(name)—— 按集合名返回类型化的 MongoDBCollection实例this.getDb()—— 返回原始 MongoDBDb实例可完全访问数据库。事务Migrator默认开启事务而 MongoDB 事务有额外要求集合需预先存在且必须运行副本集replicaset。可以考虑migrations: { transactional: false }禁用。若使用事务需要通过 MongoDB 的session选项手动为查询提供事务上下文await this.getCollection(book).updateMany({}, { $set: { updatedAt: new Date() } }, { session: this.ctx });迁移示例import { Migration } from mikro-orm/migrations-mongodb; export class MigrationTest1 extends Migration { async up(): Promisevoid { // 用 this.getCollection() 直接操作 mongodb 集合 await this.getCollection(book).updateMany({}, { $set: { updatedAt: new Date() } }, { session: this.ctx }); // 或用 this.getDb() 完全访问数据库 await this.getDb().collection(book).deleteMany({ foo: true }, { session: this.ctx }); } }已知限制MySQLMySQL 中无法回滚 DDL 变更——这类查询会被强制隐式提交事务因此无法按预期工作这是 MySQL 隐式提交语义的固有限制而非 MikroORM 缺陷。规划 MySQL 迁移时需相应设计不可逆操作。MongoDB不支持嵌套事务不做 schema diff只生成空白迁移。调试schema diff 偶尔会产出非预期查询常见原因出在属性的columnType或default/defaultRaw选项设置上。设置MIKRO_ORM_CLI_VERBOSE环境变量可开启 CLI 的 verbose 日志它同时输出用于提取当前 schema 的底层查询以及SchemaComparator中的日志帮助你理解 ORM 为何认为两列不同、具体是哪些选项有差异。调试迁移问题更简单的方式是直接使用schema:update——跳过 Migrator 层直接测试问题真正所在的 schema 层。$ MIKRO_ORM_CLI_VERBOSE1 npx mikro-orm schema:update --dump小结MikroORM 的迁移系统以「schema diff → 迁移文件 → 事务执行 → 快照比对」为核心闭环Migration类与MigrationRunner负责执行语义Migration.ts、MigrationRunner.tsMigrationStorage维护执行日志表Migrator串联生成、快照、校验与运行时 schema 上下文Migrator.ts。无论你是从零起步、为已有 schema 引入初始迁移、在 CI 中校验 schema 一致性还是面向 PR 预览与多租户场景做 schema 扩散都可以基于本文的配置与命令快速落地遇到 diff 异常时MIKRO_ORM_CLI_VERBOSE与schema:update --dump是定位问题最直接的入口。赞分享后端【免费下载链接】mikro-ormTypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, MariaDB, MS SQL Server, PostgreSQL and SQLite/libSQL databases.项目地址https://gitcode.com/gh_mirrors/mi/mikro-orm点击查看免费下载相关推荐MikroORM 迁移指南从 Schema Diff 到生产环境的多租户部署MikroORM 迁移指南从 Schema Diff 到生产环境的多租户部署 MikroORM 将数据库迁移Migrations作为一等公民内置支持基于后端MikroORM v7 数据库迁移完整指南从 schema 差异生成、快照机制到生产环境执行MikroORM v7 数据库迁移完整指南从 schema 差异生成、快照机制到生产环境执行 MikroORM 将数据库迁移Migrations作为一等公后端MikroORM 数据库迁移完全指南从 Schema Diff 到生产环境发布MikroORM 数据库迁移完全指南从 Schema Diff 到生产环境发布 MikroORM 内置了基于 umzug 的数据库迁移Migrations后端上一篇OpCore Simplify让黑苹果配置从技术挑战变成轻松体验下一篇RevokeMsgPatcher彻底告别消息撤回困扰的终极Windows工具指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表