引言
-
众所周知,OceanBase 是一款分布式数据库,同时兼容 MySQL 和 Oracle。Prisma 则是新一代的 Node.js ORM 框架,支持 MySQL、PostgreSQL 等多种查询引擎,能够极大提升数据库的开发效率和体验。那两者能否一起使用呢?
-
尝试了下,第一步连接数据库就遇到了
Unknown system variable 'socket'
的问题:
OceanBase 不兼容 socket 变量
- 给 OceanBase 社区反馈了该问题 https://github.com/oceanbase/oceanbase/issues/1936,结论是 OceanBase 不支持 socket 变量,而且预计修复版本和时间都比较靠后。即使修复了,也只是特定版本可用。
Prisma prefer_socket 参数不生效
- 那能否在 Prisma 侧绕过呢?经查询,Prisma 支持数据库连接串参数
prefer_socket
,在建连时可关闭 socket 变量查询,从而避免该问题。
DATABASE_URL="{YOUR_DATABASE_URL}?prefer_socket=false"
- 经验证,仍然出现刚刚的
Unknown system variable 'socket'
问题,说明prefer_socket=false
并未生效。
- 给 Prisma 官网提了 issue https://github.com/prisma/prisma/issues/24010,但长时间没有响应和处理,因此打算自行修复该问题。
问题排查: 梳理 Prisma 架构
- 为了定位问题,对 Prisma 架构和包的嵌套逻辑进行了梳理。
问题根因: mysql_async 驱动 bug
- 经过层层下钻,最终定位到问题原因是 Prisma 自动维护的 mysql_async 分支 存在 bug: 即使设置
prefer_socket=false
,仍然会在建连时去查询 socket 变量。
- 只需要改为绿色部分的代码,即可修复该问题,使
prefer_socket=false
生效。给 Prisma 官方提交修复 PR https://github.com/prisma/mysql_async/pull/6 后,迟迟没有回应。
问题解决: 自行构建和托管 Prisma 引擎
- 随着包括 OceanBase 和 TDSQL 在内越来越多的用户反馈,亟需解决 Prisma
prefer_socket=false
不生效的问题。
- 查阅 Prisma 文档之后,发现 Prisma 支持通过环境变量自定义引擎的下载地址和版本。
# 自定义 Prisma 引擎下载地址,默认值为 https://binaries.prisma.sh
PRISMA_ENGINES_MIRROR=""
# 自定义 Prisma 引擎版本,值为 https://github.com/prisma/prisma-engines 仓库的 commit id
BINARY_DOWNLOAD_VERSION=""
-
因此计划自行构建和托管 Prisma 引擎,需要 fork 并修改以下两个仓库:
-
fork https://github.com/prisma/mysql_async 到 https://github.com/dengfuping/mysql_async,并合并 https://github.com/prisma/mysql_async/pull/6 的修复代码
-
fork https://github.com/prisma/prisma-engines 到 https://github.com/dengfuping/prisma-engines,并将 mysql_async 指向自己维护的仓库和分支。
- 申请 AWS S3 Bucket,用于托管 Prisma 的二进制引擎。按需修改构建流水线
.github/workflows/build-engines.yml
配置 (可详见 commit),流水线执行成功即可自动上传引擎产物到 S3 上。
流水线构建 | 将引擎托管到 AWS S3 |
---|---|
使用方案: 配置环境变量
- 数据库连接串增加
prefer_socket=false
参数:
DATABASE_URL="{YOUR_DATABASE_URL}?prefer_socket=false"
-
将环境变量写入
~/.bashrc
或~/.zshrc
(取决于使用的 shell 类型) 并 source,以保证全局生效: -
注意: 不能在 .env 文件中配置,否则读取不到
-
注意: 尽量将环境变量配置到全局,否则新开命令行窗口会丢失
export PRISMA_ENGINES_MIRROR=https://oceanbase-prisma-builds.s3.ap-southeast-1.amazonaws.com
export BINARY_DOWNLOAD_VERSION=96fa66f2f130d66795d9f79dd431c678a9c7104e
- 输入
env
命令,查看环境变量是否生效:
- 重装依赖 (要求
prisma
和@prisma/client
版本在^5.20.0
及以上):
rm -rf node_modules && npm i
- 连接成功:
npx prisma db pull
- 调试小技巧: 如果按上述步骤操作仍然连接不上,或者想了解 Prisma 内部的执行流程,重装依赖时可以使用以下命令,会将 Prisma 内部的 debug 信息打印出来。
rm -rf node_modules && DEBUG="prisma:*" npm i --foreground-scripts
后续规划
-
推动 https://github.com/prisma/mysql_async/pull/6 合入,这样可以直接使用 Prisma 官方引擎,无须托管引擎和配置环境变量。
-
推动 prisma/mysql_async 同步 blackbeam/mysql_async 上游变更,可以获取最新功能和 bug 修复。
-
探索 OceanBase x Prisma 的应用场景和最佳实践。