服务端阅读 06月19日 15:57
TypeORM 支持哪些数据库?如何选择和配置?
TypeORM 能连的数据库不少,但“支持”不等于“随便换个 type 就能无痛迁移”。MySQL、PostgreSQL、SQLite 这类关系型数据库是它最常见的使用场景;MongoDB 虽然也在支持列表里,但功能边界和 SQL 数据库明显不同。选型时要同时看驱动成熟度、团队经验、迁移能力、事务需求和生产环境的运维成本。TypeORM 官方支持的数据库有哪些常见项目里会遇到的数据库大致可以分成三类。| 数据库 | TypeORM type 值 | 常用驱动 | 适合场景 ||---|---|---|---|| MySQL | mysql | mysql2 | Web 应用、传统业务系统、读写规模中等的服务 || MariaDB | mariadb | mysql2 | MySQL 兼容生态、开源替代 MySQL 的场景 || PostgreSQL | postgres | pg | 复杂查询、JSONB、地理信息、事务要求高的系统 || SQLite | sqlite | sqlite3 | 本地开发、桌面应用、小型工具、测试环境 || better-sqlite3 | better-sqlite3 | better-sqlite3 | 需要同步 API、性能更好的本地 SQLite 场景 || sql.js | sqljs | sql.js | 浏览器、纯 JS 运行环境、无需本地数据库进程的场景 || Microsoft SQL Server | mssql | mssql | Windows / .NET 技术栈、企业内部系统 || Oracle | oracle | oracledb | 大型企业、金融、电信等已有 Oracle 基础设施的系统 || CockroachDB | cockroachdb | pg | 分布式 SQL、高可用、多地域部署 || SAP HANA | sap | @sap/hana-client 或 hdb-pool | SAP 生态、企业数据平台 || Google Spanner | spanner | @google-cloud/spanner | Google Cloud 上的全球分布式关系型数据库 || MongoDB | mongodb | mongodb | 文档模型、非关系型数据,但 TypeORM 支持有限 |原文里提到的 MySQL / MariaDB、PostgreSQL、SQLite、Microsoft SQL Server、Oracle、MongoDB、CockroachDB 都是 TypeORM 里比较重要的数据库类型。补充的 better-sqlite3、sqljs、sap、spanner 也经常出现在官方支持列表或实际项目配置里。使用前先安装对应数据库驱动TypeORM 本身不内置所有数据库驱动。你配置了 type: 'postgres',还需要安装 pg;配置了 type: 'mysql',通常还要安装 mysql2。这一步漏掉时,项目启动会直接报找不到依赖。常见安装命令如下:# MySQL / MariaDBnpm install typeorm mysql2# PostgreSQL / CockroachDBnpm install typeorm pg# SQLitenpm install typeorm sqlite3# better-sqlite3npm install typeorm better-sqlite3# sql.jsnpm install typeorm sql.js# Microsoft SQL Servernpm install typeorm mssql# Oraclenpm install typeorm oracledb# SAP HANAnpm install typeorm @sap/hana-client# Google Spannernpm install typeorm @google-cloud/spanner# MongoDBnpm install typeorm mongodb如果项目使用 pnpm 或 yarn,把 npm install 换成对应命令即可。生产环境还要注意驱动的原生依赖,例如 Oracle 的 oracledb 往往需要额外的客户端库,部署容器时不能只复制 Node.js 代码。常见数据库配置示例MySQL / MariaDBMySQL 和 MariaDB 的配置很接近,差别主要在 type。如果用 MariaDB,建议明确写成 mariadb,不要因为兼容 MySQL 协议就偷懒写 mysql。import { DataSource } from 'typeorm';export const AppDataSource = new DataSource({ type: 'mysql', host: 'localhost', port: 3306, username: 'root', password: 'password', database: 'test', entities: ['src/entities/**/*.ts'], migrations: ['src/migrations/**/*.ts'], synchronize: false,});MariaDB 示例:new DataSource({ type: 'mariadb', host: 'localhost', port: 3306, username: 'root', password: 'password', database: 'test', synchronize: false,});PostgreSQLPostgreSQL 是 TypeORM 项目里很常见的选择,尤其适合需要 JSONB、复杂索引、事务和更强 SQL 能力的后端服务。new DataSource({ type: 'postgres', host: 'localhost', port: 5432, username: 'postgres', password: 'password', database: 'test', schema: 'public', entities: ['src/entities/**/*.ts'], migrations: ['src/migrations/**/*.ts'], synchronize: false,});PostgreSQL 的一个优势是类型能力更强,比如 jsonb、数组、枚举、部分索引等。但这些能力也会带来迁移成本:如果以后切到 MySQL,并不是改个连接配置就结束。SQLite / better-sqlite3 / sql.jsSQLite 适合本地、小工具、桌面端或测试环境。它不需要单独启动数据库服务,配置也最简单。new DataSource({ type: 'sqlite', database: './database.sqlite', entities: ['src/entities/**/*.ts'], synchronize: false,});如果希望使用 better-sqlite3:new DataSource({ type: 'better-sqlite3', database: './database.sqlite', entities: ['src/entities/**/*.ts'], synchronize: false,});浏览器或纯 JS 环境可以考虑 sqljs:new DataSource({ type: 'sqljs', entities: ['src/entities/**/*.ts'], synchronize: false,});SQLite 系列不要被“轻量”两个字误导。它很适合嵌入式和本地单机,但并不适合高并发写入的服务端核心库。多人同时写、长事务、复杂权限隔离这些场景,还是优先考虑 PostgreSQL 或 MySQL。Microsoft SQL ServerSQL Server 常出现在 Windows Server、Azure、企业内部系统里。new DataSource({ type: 'mssql', host: 'localhost', port: 1433, username: 'sa', password: 'yourStrong(!)Password', database: 'test', options: { encrypt: true, trustServerCertificate: true, }, entities: ['src/entities/**/*.ts'], synchronize: false,});这里的 options 经常影响连接结果。开发环境可能需要 trustServerCertificate: true,生产环境则要认真配置证书,不建议长期用“信任所有证书”的方式糊过去。OracleOracle 在大型企业里很常见,但 Node.js 部署比 MySQL、PostgreSQL 麻烦一些,尤其是客户端依赖和连接池配置。new DataSource({ type: 'oracle', host: 'localhost', port: 1521, username: 'system', password: 'password', sid: 'xe', entities: ['src/entities/**/*.ts'], synchronize: false,});Oracle 字段类型、序列、大小写标识符、分页 SQL 和日期处理都和 MySQL / PostgreSQL 有差异。已有 Oracle 基础设施时可以用;新项目如果没有强约束,不建议为了“企业级”三个字盲选。CockroachDBCockroachDB 走 PostgreSQL 协议,TypeORM 配置上和 PostgreSQL 很像,但 type 要写成 cockroachdb。new DataSource({ type: 'cockroachdb', host: 'localhost', port: 26257, username: 'root', password: '', database: 'defaultdb', ssl: false, entities: ['src/entities/**/*.ts'], synchronize: false,});它适合分布式 SQL 和高可用需求,但要接受一个现实:分布式事务、唯一索引、时间戳、重试策略都会比单机 PostgreSQL 更复杂。业务代码里要考虑事务重试,不能只按传统单库思路写。SAP HANASAP HANA 通常不是普通互联网项目的首选,但在 SAP 生态和企业数据平台里会遇到。new DataSource({ type: 'sap', host: 'localhost', port: 30015, username: 'SYSTEM', password: 'password', database: 'test', entities: ['src/entities/**/*.ts'], synchronize: false,});这类数据库的关键不在 TypeORM 配置,而在企业环境里的账号权限、网络策略、驱动安装和 DBA 协作。上线前最好让运维或 DBA 一起确认连接池、超时、字符集和权限边界。Google SpannerSpanner 面向 Google Cloud 的全球分布式数据库场景,和传统单机关系型数据库的使用习惯差异比较大。new DataSource({ type: 'spanner', projectId: 'my-gcp-project', instanceId: 'my-instance', databaseId: 'my-database', entities: ['src/entities/**/*.ts'], synchronize: false,});如果项目没有明确的全球分布式、一致性和云厂商绑定需求,Spanner 通常不是默认选择。它的价值在架构层面,不是 ORM 层面。MongoDBTypeORM 也支持 MongoDB,但要单独看待。MongoDB 不是 SQL 数据库,很多 TypeORM 在关系型数据库里的能力不能直接套用。new DataSource({ type: 'mongodb', host: 'localhost', port: 27017, database: 'test', entities: ['src/entities/**/*.ts'], synchronize: false,});MongoDB 实体通常使用 ObjectIdColumn:import { Entity, ObjectIdColumn, ObjectId, Column } from 'typeorm';@Entity()export class User { @ObjectIdColumn() id: ObjectId; @Column() name: string;}需要特别注意:TypeORM 对 MongoDB 的支持并不等同于 Mongoose 那种围绕文档数据库设计的完整体验。关系映射、迁移、QueryBuilder、事务习惯、复杂聚合这些地方都会受限。如果业务核心就是 MongoDB 文档模型,很多团队会直接选择 MongoDB 原生驱动或 Mongoose,而不是用 TypeORM 硬包一层。SQL 数据库和 MongoDB 的差异别忽略TypeORM 的主场仍然是关系型数据库。SQL 数据库里,Entity 通常对应表,Column 对应列,Relation 对应外键或中间表;迁移系统也主要围绕表结构变更工作。MongoDB 的模型完全不同。它存的是文档,天然支持嵌套对象,很多时候不需要外键和 Join。你当然可以在 TypeORM 里写 MongoDB Entity,但不要期待 @ManyToOne、leftJoinAndSelect、SQL 风格迁移这些能力都能照常使用。简单判断:需要事务、关系、报表查询、强一致结构:优先 SQL 数据库。数据结构经常变化、文档嵌套明显、关系较弱:可以考虑 MongoDB。已经决定用 MongoDB,并且会大量用聚合管道和文档特性:优先评估原生驱动或 Mongoose。选择数据库时看这几个问题团队最熟哪个数据库ORM 能降低一部分使用门槛,但不能替代数据库经验。慢查询、锁等待、索引失效、连接池打满、迁移失败,这些问题最后还是要靠数据库知识解决。团队熟 PostgreSQL,就不要为了“切换简单”硬上 Oracle;团队 MySQL 经验深,也不必因为 PostgreSQL 功能强就马上换。业务关系是否复杂电商订单、权限系统、财务流水、内容平台这类关系清晰的业务,MySQL / PostgreSQL 更稳。日志、配置快照、用户画像、表单结果这类结构变化频繁的数据,MongoDB 或 JSONB 可能更舒服。是否需要数据库特有能力PostgreSQL 的 JSONB、数组、GIN 索引很好用;MySQL 的生态和运维资料很丰富;SQLite 部署简单;CockroachDB 和 Spanner 解决的是分布式一致性问题。用了这些能力,就要接受迁移时不再“数据库无关”。部署环境是否支持有些驱动在本地跑得很顺,进容器或 CI 就开始报错。Oracle、SAP HANA、SQLite 原生模块、better-sqlite3 都可能遇到构建环境问题。生产部署前要确认镜像、系统依赖、CPU 架构和连接配置。迁移和 schema 的常见坑TypeORM 给人一种“同一套 Entity 可以跑所有数据库”的感觉,但实际项目里,schema 差异经常藏在细节里。字段类型不完全通用varchar、text、timestamp、json、uuid、enum 在不同数据库中的实现不完全一样。PostgreSQL 有 jsonb,MySQL 有自己的 JSON 类型,SQLite 对类型更宽松,Oracle 的日期和字符类型又是另一套习惯。尽量不要在通用代码里随便写数据库特有类型。如果明确只支持 PostgreSQL,那用 jsonb 没问题;如果未来要兼容 MySQL,就要提前设计抽象方式。自动同步不适合生产synchronize: true 在开发初期很方便,但生产环境必须关掉。它会根据 Entity 自动改表,遇到字段删除、类型调整、索引变化时风险很高。生产环境应该使用 migration,并在测试环境先跑一遍。new DataSource({ type: 'postgres', host: 'localhost', port: 5432, username: 'postgres', password: 'password', database: 'test', entities: ['src/entities/**/*.ts'], migrations: ['src/migrations/**/*.ts'], synchronize: false,});迁移生成结果要人工检查migration:generate 能减少手写 SQL,但不要把它当成绝对正确。字段重命名可能被识别成“删除旧列 + 新增新列”,这会导致数据丢失。索引、默认值、枚举、外键变化也要仔细看生成文件。一个比较稳的习惯是:npm run typeorm migration:generate -- src/migrations/UpdateUserTablenpm run typeorm migration:runnpm run typeorm migration:show生成后先读 migration 文件,再决定是否提交。对大表做字段修改时,最好拆成多次迁移:先加新列,再回填数据,再切读写,最后删旧列。命名和大小写会影响跨库PostgreSQL 对未加引号的标识符会转小写,MySQL 在不同系统上表名大小写行为可能不同,Oracle 对大小写和保留字也更敏感。Entity、表名、列名建议统一使用小写加下划线,少用数据库关键字。@Entity({ name: 'user_account' })export class UserAccount { @Column({ name: 'created_at' }) createdAt: Date;}这类看起来啰嗦的命名,能省掉不少跨环境问题。生产环境配置要注意什么连接池别用默认值糊弄数据库连接不是越多越好。Node.js 服务副本一多,每个进程都开连接池,很容易把数据库打满。MySQL、PostgreSQL、SQL Server 等驱动的连接池配置方式略有不同,上线前要按实例数和数据库上限计算。日志要区分开发和生产开发环境可以打开 SQL 日志,排查很方便;生产环境全量打印 SQL 可能泄露敏感参数,也会制造大量日志。建议生产只打开错误日志或慢查询监控。new DataSource({ type: 'mysql', host: 'localhost', port: 3306, username: 'root', password: 'password', database: 'test', logging: ['error'], synchronize: false,});事务和锁要按数据库特性处理同样一段事务代码,在 MySQL、PostgreSQL、CockroachDB 上的表现可能不同。隔离级别、死锁重试、行锁语法、DDL 是否能在事务里执行,都需要看数据库文档。特别是 CockroachDB 这类分布式 SQL,事务重试不是异常情况,而是应用必须处理的正常流程。不要轻易承诺“随时切库”TypeORM 的统一 API 确实能让简单 CRUD 更像一套代码,但真实系统里总会用到数据库特有能力:JSONB、全文索引、枚举、分页语法、锁、地理类型、数组、触发器、存储过程。用了以后,切库成本就会明显上升。比较靠谱的说法是:TypeORM 能降低多数据库适配成本,但不能消除数据库差异。怎么选最稳如果是普通 Node.js 后端,默认可以从 MySQL / MariaDB 或 PostgreSQL 里选。团队重视生态、运维经验和兼容性,MySQL / MariaDB 很稳;需要复杂查询、JSONB、强事务和扩展能力,PostgreSQL 更合适。本地工具、桌面应用、测试环境选 SQLite、better-sqlite3 或 sql.js。企业已有 SQL Server、Oracle、SAP HANA,就按现有基础设施接入。需要分布式 SQL,再评估 CockroachDB 或 Spanner。MongoDB 则要单独判断:如果只是想用 TypeORM 顺手连一下可以,但如果业务大量依赖文档数据库特性,最好认真比较 TypeORM MongoDB 支持和 MongoDB 原生生态的差别。TypeORM 支持的数据库很多,真正影响项目质量的不是列表有多长,而是你有没有选一个团队能维护、迁移能控制、生产问题能排查的数据库。