はじめに
はじめまして、2021/11 にキャリア入社したTIGの穴井です。失敗談をテーマにした連載の2本目です。
Go の O/Rマッパ(Object-relational mapping)である gorm
利用時の構造体にて、サロゲートキーの型が int32
であることに起因して、当該フィールドが数年でオーバーフローしそうだった件について、なぜ実装時に気づけなかったのか、記載いたします。
背景
既存システムに機能追加することで、これまでとは比べ物にならないデータ量を扱うシステムとなることがあると思います。私が参画しているプロジェクトでも扱うデータ量が大幅に急増し、結果として Go の構造体の int32
のサロゲートキーが数年でオーバーフローすることが見込まれる状況となりました。
なぜ実装時に気づけなかったのか
システム開発を行う際に、開発者が共通で利用する部品を作り込むと思いますが、
その部品の利用に問題がありました。
私が参画しているプロジェクトは、全てのテーブルでサロゲートキーとシステムカラムを定義するという開発規約があるため、これらを表現する構造体を1つ定義しておき、構造体の埋め込みを利用して O/Rマッパ を利用していました。また、サロゲートキーは ID という名称にするテーブル定義規約があり、ID はデータが insert されるたびに increment されるテーブル定義 (PostgreSQL の serial 型) となっています。
上記をコードで表すと以下の通りとなります。
// BaseColumns 共通カラムの構造体 |
// CreateSampleModel SampleModel を DB に書き込む関数(利用例) |
このような規約がある中で実装を愚直に進めた結果、データ量に関する考慮漏れが発生し、
int32 のサロゲートキーを利用してしまい、数年でオーバーフローが見込まれる状況となってしまいました。
今回はサロゲートキーのオーバフロー問題ということで下記に int32, int64 の最大値を示します。
int32 | int64 |
---|---|
2,147,483,647 | 9,223,372,036,854,775,807 |
本事象では、DB で自動採番された ID が 2,147,483,647 を超えた際に Go の構造体にパースできずオーバーフローすることが見込まれました。
機能追加により約21億のデータを扱うシステムとなることは、稀なケースですが、このようなオーバーフロー問題はすべての人が遭遇する可能性がある事象だと思います。本事象に遭遇したことで、改めて、データ量と型設定について見直すいい機会となりました。
※本事象発覚後、int64のサロゲートキーを利用するようソースを修正しました。
さいごに
同じ苦しみを味わう人が出ないよう、本記事にて供養いたします。
次は原さんのGo言語で定数として扱いたいmapを毎回アロケートさせて性能劣化した話です。