Sequelize 7 MariaDB 方言包 @sequelize/mariadb 演进全解:从包拆分到连接选项体系重构
【免费下载链接】sequelizeFeature-rich ORM for modern Node.js and TypeScript, it supports PostgreSQL (with JSON and JSONB support), MySQL, MariaDB, SQLite, MS SQL Server, Snowflake, Oracle DB, DB2 and DB2 for IBM i.项目地址: https://gitcode.com/gh_mirrors/se/sequelize
packages/mariadb/CHANGELOG.md记录了@sequelize/mariadb包在 Sequelize 7 开发周期(7.0.0-alpha.40 → alpha.48)内的每一次变更,其中既包含 MariaDB 连接器驱动的升级与错误处理的优化,也包含了 Sequelize 7 对整条 MySQL 系方言链路的破坏性重构(连接 URL 解析、方言专属选项、连接池归属等)。本文以该变更日志为骨架,结合 packages/mariadb 下的源码实现,逐条拆解这些变化的来龙去脉,帮助你在升级到 Sequelize 7 时理解并迁移 MariaDB 相关的配置写法。
版本演进一览
变更日志覆盖了从7.0.0-alpha.40到7.0.0-alpha.48共 9 个预发布版本。其中大部分版本(alpha.42、alpha.44、alpha.45、alpha.46、alpha.47、alpha.48)仅随主仓库整体发版而进行版本号同步("Version bump only"),真正包含实质变更是以下四个版本:
| 版本 | 发布日期 | 变更类别 | 核心内容 |
|---|---|---|---|
| 7.0.0-alpha.40 | 2024-04-11 | Breaking / Features | MariaDB 方言拆分为独立包;连接 URL 按方言解析;选项体系大规模重构 |
| 7.0.0-alpha.41 | 2024-05-17 | Bug Fix | 在 query generator 与 query interface 上设置正确的 sequelize dialect 类型 |
| 7.0.0-alpha.43 | 2024-10-04 | Bug Fix | 优化错误信息中的低效正则;升级 mariadb 驱动至 v3.3.2 |
| 7.0.0-alpha.48 | 2026-02-04 | — | 当前包版本(7.0.0-alpha.48) |
当前仓库中 packages/mariadb/package.json 的版本即为7.0.0-alpha.48,其依赖mariadb驱动已进一步更新到^3.5.4。
从核心包拆分出 @sequelize/mariadb
变更日志中最重要的结构性变化是 "move mariadb to the@sequelize/mariadbpackage"(issue #17198)。在 Sequelize 7 之前,MariaDB 支持内置于sequelize主包,而在 Sequelize 7 中,每个数据库方言都被抽取为独立的 npm 包,与@sequelize/postgres、@sequelize/mysql、@sequelize/sqlite3等并列。
这一拆分的直接后果是安装方式改变(见该版本 BREAKING CHANGES 最后一条):
- 不再需要安装
mariadb驱动包,而是安装@sequelize/mariadb; @sequelize/mariadb内部把mariadb(MariaDB 官方 Node.js 连接器)声明为自己的依赖(见 package.json),用户无需手动安装驱动;- 使用方通过
Sequelize构造函数的dialect选项直接传入方言类。
典型用法如下:
import { Sequelize } from '@sequelize/core'; import { MariaDbDialect } from '@sequelize/mariadb'; const sequelize = new Sequelize({ dialect: MariaDbDialect, host: 'localhost', port: 3306, user: 'root', password: 'password', database: 'mydb', });该包导出的核心模块(见 packages/mariadb/src/index.ts)包括MariaDbDialect、MariaDbConnectionManager、MariaDbQueryGenerator、MariaDbQueryInterface与MariaDbQuery五个类,完整覆盖了从连接管理、SQL 生成到结果格式化与错误映射的全链路。
连接 URL 改为按方言解析
在 alpha.40 之前,Sequelize 使用一套通用的 URL 解析逻辑处理所有方言。此次变更(issue #17252)将 "parse theurloption based on the dialect" 落地:每个方言类现在自行实现parseConnectionUrl(),Sequelize 只负责把用户传入的url字符串交给当前方言去解析。
MariaDB 的实现位于 packages/mariadb/src/dialect.ts:通过parseCommonConnectionUrlOptions解析,只允许mariadb协议,并把 URL 的各组成部分映射到连接选项上:
hostname→hostport→portpathname→databaseusername→userpassword→password- 其余 query 参数按字符串 / 布尔 / 数字三类白名单映射到对应连接选项
因此你现在可以这样配置:
const sequelize = new Sequelize({ dialect: MariaDbDialect, url: 'mariadb://user:password@localhost:3306/mydb?charset=utf8mb4&connectTimeout=10000', });packages/mariadb/src/dialect.test.ts 中的单元测试验证了上述映射结果:mariadb://user:password@localhost:1234/dbname?charset=utf8mb4会被解析为{ host: 'localhost', port: 1234, user: 'user', password: 'password', database: 'dbname', charset: 'utf8mb4' }。
需要特别注意的是,本次变更同时声明:db2、ibmi、snowflake和sqlite方言不再接受url选项,而 MySQL 系(含 MariaDB)保留该能力。
Sequelize 7 选项体系重构(重点 BREAKING CHANGES)
alpha.40 的变更日志集中宣告了 Sequelize 7 对全局选项系统的重构,这些破坏性变更对 MariaDB 用户同样生效,直接影响迁移时的配置写法:
1. 构造函数只接受一个 option bag
所有其他构造函数签名(例如把url作为字符串直接传入的旧写法)都被移除:
// 旧写法(已移除) new Sequelize('mariadb://user:password@localhost:3306/mydb'); // 新写法 new Sequelize({ dialect: MariaDbDialect, url: 'mariadb://user:password@localhost:3306/mydb' });2.dialectOptions被移除
原先放在dialectOptions里的所有驱动选项现在直接平铺在 option bag 顶层,与其他选项平级。MariaDB 方言支持哪些驱动选项由白名单控制(见下文"连接选项白名单"),以保证不会传入破坏 Sequelize 协议格式的非法配置。
3. 连接池归属变化
连接池不再挂在 connection manager 上,而是直接挂在 Sequelize 实例上,通过sequelize.pool访问。这一点可以在 packages/mariadb/src/connection-manager.ts 中得到印证——当连接抛出ESOCKET、ECONNRESET、EPIPE、PROTOCOL_CONNECTION_LOST等错误时,正是调用this.sequelize.pool.destroy(connection)来销毁连接。
4.sequelize.config被移除,连接信息归一化
所有数据库连接信息被归一化为sequelize.options.replication.write(总是存在)和sequelize.options.replication.read(仅启用读复制时存在)。MariaDB 方言的getDefaultSchema()也据此实现——它返回this.sequelize.options.replication.write.database作为默认 schema(见 dialect.ts)。
5.sequelize.options被冻结
sequelize.options现在是归一化后的只读配置,实例创建后不可再修改;如需访问创建实例时用户传入的原始配置,请使用sequelize.rawOptions。
6. 驱动替换选项拆分
原先的dialectModule选项被拆分为按 npm 包命名的独立选项;dialectModulePath被彻底移除(以改善与打包工具的兼容性)。对 MariaDB 方言来说,对应的是mariaDbModule(详见下一节)。
7.sequelize.sync的match选项不再支持
如果曾依赖match正则过滤同步对象,需要联系维护团队反馈使用场景,以设计替代方案。
重新支持连接器库覆盖:mariaDbModule
alpha.40 的 Features 中有一条 "re-add the ability to override the connector library"(issue #17219),即恢复通过自定义库替换默认驱动连接器的能力。
对 MariaDB 方言而言,这就是 packages/mariadb/src/dialect.ts 中定义的MariaDbDialectOptions.mariaDbModule选项:传入的库必须与mariadbnpm 包的 API 兼容。其类型定义在 connection-manager.ts 中为type MariaDbModule = typeof MariaDb,连接管理器构造时执行this.#lib = dialect.options.mariaDbModule ?? MariaDb,因此不传该选项时默认使用官方mariadb驱动。
官方注释明确提示:该选项仅应作为最后手段使用,Sequelize 团队无法保证其兼容性。典型的动机是使用打了补丁的 fork 版本,或需要与特定驱动版本对齐:
import { MariaDbDialect } from '@sequelize/mariadb'; import patchedMariaDb from 'mariadb-patched'; const sequelize = new Sequelize({ dialect: MariaDbDialect, mariaDbModule: patchedMariaDb, // ...其余连接选项 });同属此方言专属选项的还有showWarnings:设为true后,执行查询时若驱动返回的warningStatus > 0,会调用logWarnings记录警告(见 packages/mariadb/src/query.js)。
驱动升级与错误处理优化
alpha.43 包含两条 MariaDB 专属修复:
- 升级
mariadb至 v3.3.2(issue #17518):当前仓库依赖已进一步演进为^3.5.4。驱动升级通常带来协议兼容性与连接池行为改进,是 MariaDB 方言与新版服务器版本保持兼容的常规手段。 - 优化错误信息解析中的低效正则(issue #17508):对应 packages/mariadb/src/query.js 的
formatError实现——它依据 MariaDB 的错误码(errno)把原始驱动错误映射为 Sequelize 的语义化错误类型:1062(ER_DUP_ENTRY)→UniqueConstraintError,并尝试从错误消息中提取重复键与字段值;1451/1452(ER_ROW_IS_REFERENCED/ER_NO_REFERENCED_ROW)→ForeignKeyConstraintError,通过正则从消息中解析出约束名、表名与字段;1091(ER_CANT_DROP_FIELD_OR_KEY)→UnknownConstraintError;1213(ER_DEADLOCK)→ 死锁时 MariaDB 会自动回滚事务,但 Sequelize 仍会额外发起一次回滚以确保连接被正确释放(见 query.js);- 其余错误 → 统一的
DatabaseError。
此外,alpha.41 修复了 query generator 与 query interface 上的 dialect 类型设置问题,确保方言元数据在整条查询链路中一致传递。
连接选项白名单:MariaDB 驱动选项的可配范围
由于 Sequelize 7 要求"方言专属选项必须经过白名单校验,确保不破坏 Sequelize 的正常工作",packages/mariadb/src/_internal/connection-options.ts 中集中维护了允许直接配置的驱动选项,按类型分为三类:
字符串类:host、port之外还包括database、user、password、charset、collation、socketPath、initSql、rsaPublicKey、cachingRsaPublicKey。
布尔类:debug、debugCompress、logParam、trace、multipleStatements、ssl、compress、logPackets、forceVersionCheck、foundRows、allowPublicKeyRetrieval、metaEnumerable、bulk、pipelining、permitLocalInfile、checkDuplicate。
数值类:port、connectTimeout、socketTimeout、debugLen、maxAllowedPacket、maxAllowedColumns、keepAliveDelay、prepareCacheLength、queryTimeout。
另有sessionVariables、connectAttributes、logger、infileStreamFactory、stream等额外选项。这些选项会通过 URL query 参数(对应各类型白名单)与 option bag 两种方式生效。
同时,connection-manager.ts 明确禁止用户配置一批会与 Sequelize 期望格式冲突的选项,包括typeCast、timezone、namedPlaceholders、arrayParenthesis、insertIdAsNumber、metaAsArray、rowsAsArray、nestTables、dateStrings、decimalAsNumber、bigIntAsNumber、supportBigNumbers、bigNumberStrings、autoJsonMap、checkNumberRange、permitSetMultiParamEntries。其中typeCast由 Sequelize 自己注入(用于按方言注册的数据库类型解析器把驱动原始值转换为 JS 值),timezone则由 Sequelize 全局timezone选项接管。
底层实现:连接建立与时区处理
变更日志虽未逐条列出连接管理细节,但结合源码可以看出 MariaDB 方言在连接层面做了三件关键事(connection-manager.ts):
- 时区归一化:MariaDB 驱动不支持命名时区(如
America/New_York),Sequelize 会通过timeZoneToOffsetString把它转换为偏移量字符串(如-04:00);若未设置keepDefaultTimezone,还会在initSql中追加SET time_zone = '...'确保会话时区与全局配置一致。 - 类型转换注入:连接配置强制注入
typeCast,把 MariaDB 的数据库类型 ID 交给方言注册的类型解析器。这些解析器定义在 packages/mariadb/src/_internal/data-types-db.ts:DATETIME按全局时区补全偏移、LONGLONG与BIGINT以字符串形式返回(保持向后兼容)、GEOMETRY返回wkx解析后的对象。 - 错误分类:把驱动错误码映射为 Sequelize 的连接级错误(
ConnectionRefusedError、AccessDeniedError、HostNotFoundError、HostNotReachableError、InvalidConnectionError或通用ConnectionError),并记录服务器版本到sequelize实例上。
方言能力声明集中在 packages/mariadb/src/dialect.ts 的MariaDbDialect.supports:例如支持LOCK IN SHARE MODE(forShare)、INSERT IGNORE与ON DUPLICATE KEY UPDATE、JSON 操作、REGEXP、SET FOREIGN_KEY_CHECKS、IF NOT EXISTS建表/删列等。最低支持的服务端版本为10.4.30(见 dialect.ts)。
从旧版迁移到 Sequelize 7 MariaDB 配置检查清单
综合变更日志与源码,从 Sequelize 6 / 早期 alpha 迁移时可以按以下清单逐项核对:
- 安装包:卸载
mariadb直接依赖,改装@sequelize/mariadb,并通过dialect: MariaDbDialect显式声明方言。 - URL 写法:连接串必须以
mariadb://开头(只认该协议),且必须放入url选项,不能再作为构造函数的第一个字符串参数。 - 选项平铺:把
dialectOptions内的驱动配置全部平铺到 option bag 顶层;白名单之外的驱动选项(如typeCast、rowsAsArray、dateStrings等)不允许自行设置。 - 连接池与元数据访问:需要操作连接池时改用
sequelize.pool;读取连接信息时使用sequelize.options.replication.write(和可选的replication.read);创建参数可查sequelize.rawOptions。 - 连接器覆盖:如需替换驱动实现,使用
mariaDbModule(仅限与mariadbAPI 兼容的库),并自行承担兼容性风险。 - 时区:命名时区由 Sequelize 自动转换为偏移量并写入会话,无需手动处理;如需保持数据库默认时区,设置
keepDefaultTimezone: true。 - 错误处理:唯一键冲突、外键约束、死锁等错误已映射为对应的 Sequelize 错误类,可直接按类型捕获,无需再解析驱动原始错误码。
以上每一条都能在当前仓库的 packages/mariadb 源码与 packages/mariadb/src/dialect.test.ts、packages/mariadb/src/query.test.ts 测试用例中找到对应实现,可作为迁移验证与问题排查的参考。
【免费下载链接】sequelizeFeature-rich ORM for modern Node.js and TypeScript, it supports PostgreSQL (with JSON and JSONB support), MySQL, MariaDB, SQLite, MS SQL Server, Snowflake, Oracle DB, DB2 and DB2 for IBM i.项目地址: https://gitcode.com/gh_mirrors/se/sequelize
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考