问题背景
- 按照 Drizzle x MySQL 的快速上手文档,在 oceanbase-ce 4.2.1.9 版本 (Docker latest tag),执行 Drizzle 的迁移命令时,出现以下报错: feat: Add drizzle sample for javascript · oceanbase/ob-samples@3bb6751 · GitHub
- 在 Drizzle 中定义的
users
业务表 schema 如下:
import { mysqlTable, serial, varchar } from "drizzle-orm/mysql-core";
export const usersTable = mysqlTable("users", {
id: serial().primaryKey(),
email: varchar({ length: 255 }).notNull().unique(),
name: varchar({ length: 255 }).notNull(),
});
- 对应的建表语句:
CREATE TABLE `users` (
`id` serial AUTO_INCREMENT NOT NULL,
`email` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
CONSTRAINT `users_id` PRIMARY KEY(`id`),
CONSTRAINT `users_email_unique` UNIQUE(`email`)
);
问题原因
- 该 schema 在 OB Cloud Free Trail 实例 (4.3.3 版本) 下是可以迁移成功的,因此怀疑是版本问题:
- 在官网搜索 serial 关键字,发现从 OB 4.2.3 版本开始才支持 SERIAL 数据类型。因此该问题本质是 OB 4.2.3 以下版本不兼容 MySQL 的 SERIAL 数据类型。
解决方案
方案 1: 修改 OB 版本
- 使用 oceanbase-ce 4.2.3 及以上版本: 在 CI 场景下可以通过 GitHub - oceanbase/setup-oceanbase-ce: Action to setup OceanBase CE. 进行设置。
- 执行结果: feat: Add drizzle sample for javascript · oceanbase/ob-samples@a6528a2 · GitHub
方案 2: 修改 schema
- 使用 bigint + autoincrement 代替 serial,用于声明自增 ID:
-import { mysqlTable, serial, varchar } from "drizzle-orm/mysql-core";
+import { mysqlTable, bigint, varchar } from "drizzle-orm/mysql-core";
export const usersTable = mysqlTable("users", {
- id: serial().primaryKey(),
+ id: bigint({ mode: "bigint" }).autoincrement().primaryKey(),
email: varchar({ length: 255 }).notNull().unique(),
name: varchar({ length: 255 }).notNull(),
});
- 对应的建表语句:
CREATE TABLE `users` (
- `id` serial AUTO_INCREMENT NOT NULL,
+ `id` bigint AUTO_INCREMENT NOT NULL,
`email` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
CONSTRAINT `users_id` PRIMARY KEY(`id`),
CONSTRAINT `users_email_unique` UNIQUE(`email`)
);
- 重新执行,仍然出现
serial
错误: feat: Add drizzle sample for javascript · oceanbase/ob-samples@08c124d · GitHubusers
业务表,而是Drizzle 用于保存迁移历史的__drizzle_migrations
表。
方案 3: 修改 Drizzle 以避免触发 serial 的兼容性问题
-
在 Drizzle 社区搜索后,发现该问题在 PostgreSQL、SQLite 等数据库上也存在,相关 issue 和讨论:
- [BUG]: error: type "serial" does not exist · Issue #2183 · drizzle-team/drizzle-orm · GitHub (PostgreSQL)
- [BUG]: sqlite __drizzle_migrations id is of "SERIAL" type, which is not a valid type in sqlite · Issue #1227 · drizzle-team/drizzle-orm · GitHub (SQLite)
- Updated Migration Process · drizzle-team/drizzle-orm · Discussion #2624 · GitHub (社区讨论)
-
为了 OB 4.2.3 以下版本以及 PostgreSQL、SQLite 等数据库可以正常使用 Drizzle,已提 PR feat(config): Add migrations.tableIdType by dengfuping · Pull Request #3721 · drizzle-team/drizzle-orm · GitHub 帮助 Drizzle 新增
migrations.tableIdType
配置,用于绕过 serial 数据类型的兼容性问题。 -
migrations.tableIdType
配置用法:
import { defineConfig } from "drizzle-kit";
export default defineConfig({
migrations: {
+ tableIdTable: 'bigint AUTO_INCREMENT',
},
});
- 迁移时
__drizzle_migrations
的建表语句:
create table if not exists `__drizzle_migrations` (
- id serial primary key,
+ id bigint AUTO_INCREMENT primary key,
hash text not null,
created_at bigint
);