🐶 PgBouncerで諦めていたSETとLISTEN/NOTIFYが使える — Rust製プーラー「PgDog」
Rust+Tokio製のPostgresプロキシPgDog。内蔵SQLパーサーでセッション状態を維持し、トランザクションプーリングの「抽象化の漏洩」を潰しにきた。
PgBouncerのトランザクションモードには、暗黙の「使ってはいけないSQL」リストがある。SETで変えたセッション設定は次のクエリで別の接続に飛ばされて消える。LISTEN/NOTIFYは機能しない。プリペアドステートメントも長らく鬼門だった。
知らずに踏むと、ローカルでは動くのに本番でだけ挙動が変わる。接続プーリングという抽象が、SQLの意味論に穴を開けて漏れてくる——いわゆる抽象化の漏洩だ。
「Why we built yet another Postgres connection pooler」という開き直ったタイトルのブログで、PgDogの開発チームがこの問題を正面から説明していた。「またプーラー作ったの?」への答えがちゃんとある。
SQLパーサーを内蔵するという力技
PgDogはRust + Tokio(非同期ランタイム)で書かれたPostgres用プロキシで、接続プーリング・ロードバランシング・シャーディングを1つに統合している。既存プーラーとの決定的な違いは、SQLパーサーを内蔵していることだ。
クライアントが投げたクエリを字面で中継するのではなく、パースして意味を見る。SETを検出したらそのセッション状態をクライアントごとに記憶し、どのサーバー接続に載せ替えても再適用する。LISTEN/NOTIFYはプロキシがPub/Subの中継役になる。トランザクションの意味論も保持する。
つまり「トランザクションプーリングの効率」と「セッションプーリングの互換性」を両取りしにきている。パース分のオーバーヘッドをRustの速度で飲み込む、という設計判断だ。
数字と足元
ライセンスはAGPL v3で、GitHubスターは3,400超。公式ブログは毎秒200万クエリを捌く本番実績を主張している。この数字は自己申告なので、鵜呑みにはしないでおく。ただHacker Newsには2023年の初出から何度も上がっていて、開発が続いているのは確かだ。
シャーディング機能まで含めると、比較対象はPgBouncerというよりCitusやVitess(MySQL界のシャーディングプロキシ)に近づいていく。「プーラーのついでにシャーディングも」なのか「シャーディングプロキシがプーリングも」なのかで、評価軸が変わるプロダクトだと思う。
うちは今のところPgBouncerで困るほどの規模のDBを持っていないんですが、「SETが普通に使える」だけでも、あの暗黙のNGリストを新人に説明する仕事が消えるのはでかい。抽象化の漏洩は、ドキュメントではなく実装で塞ぐのが正しい。そう言い切れるプロダクトが増えてきたのは、いい傾向じゃないですか。