【成功】Drizzle ORMのPlanetScaleをTiDB Serverlessに移行したい
よって、Drizzle ORMでTiDB Serverlessを使いたい場合は、以下のような実装で利用できる
import { drizzle } from "drizzle-orm/mysql2";
import { createConnection } from "mysql2";
const connection = createConnection({
host: Deno.env.get("DB_HOST"),
user: Deno.env.get("DB_USERNAME"),
password: Deno.env.get("DB_PASSWORD"),
database: "cinelog",
/**
* NOTE: mysql2内の`node:tls`のデフォルトCAを使うための設定
* @see https://zenn.dev/link/comments/378474ec5af4e7
*/
ssl: {},
});
export const db = drizzle(connection);
PingCAP社のbohnenさん、ありがとうございました
PlanetScaleの無料枠が4月8日になくなることが、公式ブログで告知された
代替として、TiDB公式がTwitterで勧めてきたTiDB Serverlessに移行を試みてみる移行対象はシネログという映画館での鑑賞作品記録個人サイト
前々から不意にDB吹き飛ばした用にローカルにSQLファイルは置いているので、それを元にTiDB上に同じデータを展開する最初、Chat2QueryというページでCREATE TABLE
をすればテーブルが作成できるのかと思ったがそうではなかった
あくまでデータ参照用っぽい
これは誤りで、そもそもCREATE DATABASE
をしていなかった私のアホの所業だった
TiDB公式に聞いたところ、なんとQiitaの記事を教えてもらった
やり取りは英語でやってるけど、実はこれ日本法人の方が返してるんじゃないかって思った割と公式が潤沢に情報を提供しているようなので、ここからDrizzle ORMでの移行パターンを記す
Drizzle ORMとTiDB双方に公式資料は存在しない模様
なので、TiDBをMySQLだとしてDrizzle ORMのMySQLスタートガイドを利用する
なおDenoで書いているが、Node.jsと基本的に変わらないと思っている
接続の実装は以下
import { drizzle } from "drizzle-orm/mysql2";
import { createConnection } from "mysql2";
const connection = createConnection({
host: Deno.env.get("DB_HOST"),
user: Deno.env.get("DB_USERNAME"),
password: Deno.env.get("DB_PASSWORD"),
database: "cinelog",
});
export const db = drizzle(connection);
すると以下のようなエラーが出た
Error: Connections using insecure transport are prohibited. See https://docs.pingcap.com/tidbcloud/secure-connections-to-serverless-tier-clusters
at PromiseConnection.query (file:///home/windchime-yk/.cache/deno/npm/registry.npmjs.org/mysql2/3.9.2/promise.js:94:22)
at MySql2PreparedQuery.execute (file:///home/windchime-yk/.cache/deno/npm/registry.npmjs.org/drizzle-orm/0.27.2/mysql2/index.mjs:51:37)
at QueryPromise.execute (file:///home/windchime-yk/.cache/deno/npm/registry.npmjs.org/drizzle-orm/0.27.2/session-9628aea0.mjs:1150:31)
at QueryPromise.then (file:///home/windchime-yk/.cache/deno/npm/registry.npmjs.org/drizzle-orm/0.27.2/alias-3e926a50.mjs:636:21)
at eventLoopTick (ext:core/01_core.js:169:7) {
message: "Connections using insecure transport are prohibited. See https://docs.pingcap.com/tidbcloud/secure-c"... 38 more characters,
code: "ER_UNKNOWN_ERROR",
errno: 1105,
sql: undefined,
sqlState: "HY000",
sqlMessage: "Connections using insecure transport are prohibited. See https://docs.pingcap.com/tidbcloud/secure-c"... 38 more characters
}
接続が安全ではない、というエラーが表示されURLが案内されるので、以下を読む
話は逸れるが現在、Drizzle ORMはTiDB Serverless Driverに対応していないようで、Issueがいくつか立っている
また別場だが、Issueのコメントで共同創業者がTiDB対応について言及していたので、どこかのタイミングで追加はされるはず……なおMySQL2を使った場合に出るのはcreateConnectionのsslに設定すれば直るらしいのだが、ファイルを読み込まない
Uncaught (in promise) TypeError: Unknown SSL profile '~/isrgrootx1.pem'
そこで、そもそも実装を読み間違えている可能性を考え、実装を確認したところ読み間違えていた./constants/ssl_profiles.js
を参照しているらしい
./constants/ssl_profiles.js
の内部を見たところ、Amazon RDSの証明書らしきものが直書きされている
実装を見る限り、sslの部分にAmazon RDS
と書けば、当該エラーは回避できるらしい
const connection = createConnection({
host: Deno.env.get("DB_HOST"),
user: Deno.env.get("DB_USERNAME"),
password: Deno.env.get("DB_PASSWORD"),
database: "cinelog",
ssl: "Amazon RDS"
});
なので、次のエラーを確認するために記載してみたところ……
なんか通ってしまった
あれぇ……???
TiDBは内部的にAWSを使っているので、それが起因してたりするのだろうか
ちなみに、しばらくすると以下のエラーが出る
error: Uncaught Error: read UNKNOWN
at __node_internal_captureLargerStackTrace (ext:deno_node/internal/errors.ts:91:9)
at __node_internal_errnoException (ext:deno_node/internal/errors.ts:139:10)
at TCP.onStreamRead [as onread] (ext:deno_node/internal/stream_base_commons.ts:209:20)
at TCP.#read (ext:deno_node/internal_binding/stream_wrap.ts:245:12)
at eventLoopTick (ext:core/01_core.js:169:7)
いけちゃったなぁ……正規の手段なのかこれ……????
→動いていたので聞いてみます
挙動としては想定されていないものだったようで、PingCAP社のbohnenさんがTiDBのmysql2サンプルで試したところ、動作しなかった
Zenn Scrapsにもまとめてくださった
私の方は引き続き繋がっていて謎だが、これは想定外挙動として無視したほうが良さそう
sslについては、空オブジェクトを渡すことでnode:tls
モジュールがMozillaのCAを利用するそうなので、それをすることで接続は叶った